packages feed

quic-0.3.3: Network/QUIC/Utils.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}

module Network.QUIC.Utils where

import qualified Control.Exception as E
import Control.Monad (replicateM)
import qualified Data.ByteString as BS
import Data.ByteString.Base16
import qualified Data.ByteString.Char8 as C8
import Data.ByteString.Internal (ByteString (..))
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as Short
import Data.Char (chr)
#if __GLASGOW_HASKELL__ < 910
import Data.List (foldl')
#endif
import Data.Word
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (Ptr, plusPtr)
import System.Random (randomIO)

-- GHC 8.0 does not provide fromRight.
fromRight :: b -> Either a b -> b
fromRight _ (Right b) = b
fromRight b _ = b

dec16 :: ByteString -> ByteString
dec16 = fromRight "" . decode

enc16 :: ByteString -> ByteString
enc16 = encode

dec16s :: ShortByteString -> ShortByteString
dec16s = Short.toShort . fromRight "" . decode . Short.fromShort

enc16s :: ShortByteString -> ShortByteString
enc16s = Short.toShort . encode . Short.fromShort

shortToString :: ShortByteString -> String
shortToString = map (chr . fromIntegral) . Short.unpack

getRandomOneByte :: IO Word8
getRandomOneByte = randomIO

getRandomBytes :: Int -> IO ShortByteString
getRandomBytes n = Short.pack <$> replicateM n getRandomOneByte

{-# INLINE totalLen #-}
totalLen :: [ByteString] -> Int
totalLen = foldl' (\n bs -> n + BS.length bs) 0

sum' :: (Functor f, Foldable f) => f Int -> Int
sum' = foldl' (+) 0

withByteString :: ByteString -> (Ptr Word8 -> IO a) -> IO a
withByteString (PS fptr off _) f = withForeignPtr fptr $ \ptr ->
    f (ptr `plusPtr` off)

shortpack :: String -> ShortByteString
shortpack = Short.toShort . C8.pack

ignore :: E.SomeException -> IO ()
ignore se
    | isAsyncException se = E.throwIO se
    | otherwise = return ()

isAsyncException :: E.Exception e => e -> Bool
isAsyncException e =
    case E.fromException (E.toException e) of
        Just (E.SomeAsyncException _) -> True
        Nothing -> False

throughAsync :: IO a -> E.SomeException -> IO a
throughAsync action (E.SomeException e)
    | isAsyncException e = E.throwIO e
    | otherwise = action