-- | -- Module : Codec.Binary.Util -- Copyright : (c) 2009 Magnus Therning -- License : BSD3 -- -- Utility functions used in the other module. module Codec.Binary.Util ( toHex , fromHex , EncIncData(..) , EncIncRes(..) , DecIncData(..) , DecIncRes(..) , encoder , decoder ) where import Data.Array import Data.Bits import Data.Char import Data.Word import qualified Data.Map as M -- {{{1 hex enc/dec assoc list and maps hexEncMap = zip [0..] "0123456789ABCDEF" hexEncodeArray :: Array Word8 Char hexEncodeArray = array (0, 16) hexEncMap hexDecodeMap :: M.Map Char Word8 hexDecodeMap = M.fromList [(b, a) | (a, b) <- hexEncMap] -- {{{1 toHex toHex :: Word8 -> String toHex o = let hn = o `shiftR` 4 ln = o .&. 0xf in [hexEncodeArray ! hn, hexEncodeArray ! ln] -- {{{1 fromHex fromHex :: String -> Maybe Word8 fromHex = let dec [Just hn, Just ln] = let o = hn `shiftL` 4 .|. ln in Just o dec _ = Nothing in dec . map (flip M.lookup hexDecodeMap . toUpper) -- {{{1 incremental coding -- | Data type for the incremental encoding functions. data EncIncData = EChunk [Word8] -- ^ a chunk of data to be encoded | EDone -- ^ the signal to the encoder that the stream of data is ending -- | Data type for the result of calling the incremental encoding functions. data EncIncRes i = EPart i (EncIncData -> EncIncRes i) -- ^ a partial result together with the continuation to use for further encoding | EFinal i -- ^ the final result of encoding (the response to 'EDone') encoder f os = case f (EChunk os) of EPart r1 f' -> case f' EDone of EFinal r2 -> r1 ++ r2 -- | Data type for the incremental decoding functions. data DecIncData i = DChunk i -- ^ a chunk of data to be decoded | DDone -- ^ the signal to the decoder that the stream of data is ending -- | Data type for the result of calling the incremental encoding functions. data DecIncRes i = DPart [Word8] (DecIncData i -> DecIncRes i) -- ^ a partial result together with the continuation to user for further decoding | DFinal [Word8] i -- ^ the final result of decoding (the response to 'DDone') | DFail [Word8] i -- ^ a partial result for a failed decoding, together with the remainder of the data passed in so far decoder :: (DecIncData i -> DecIncRes i) -> i -> Maybe [Word8] decoder f s = let d = f (DChunk s) in case d of DFinal da _ -> Just da DFail _ _ -> Nothing DPart da f -> let d' = f DDone in case d' of DFinal da' _ -> Just $ da ++ da' DFail _ _ -> Nothing DPart _ _ -> Nothing -- should never happen