diff options
Diffstat (limited to 'src/Codec/Binary/Util.hs')
-rw-r--r-- | src/Codec/Binary/Util.hs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/Codec/Binary/Util.hs b/src/Codec/Binary/Util.hs new file mode 100644 index 0000000..feaad01 --- /dev/null +++ b/src/Codec/Binary/Util.hs | |||
@@ -0,0 +1,82 @@ | |||
1 | -- | | ||
2 | -- Module : Codec.Binary.Util | ||
3 | -- Copyright : (c) 2009 Magnus Therning | ||
4 | -- License : BSD3 | ||
5 | -- | ||
6 | -- Utility functions used in the other module. | ||
7 | module Codec.Binary.Util | ||
8 | ( toHex | ||
9 | , fromHex | ||
10 | , EncIncData(..) | ||
11 | , EncIncRes(..) | ||
12 | , DecIncData(..) | ||
13 | , DecIncRes(..) | ||
14 | , encoder | ||
15 | , decoder | ||
16 | ) where | ||
17 | |||
18 | import Data.Array | ||
19 | import Data.Bits | ||
20 | import Data.Char | ||
21 | import Data.Word | ||
22 | import qualified Data.Map as M | ||
23 | |||
24 | -- {{{1 hex enc/dec assoc list and maps | ||
25 | hexEncMap = zip [0..] "0123456789ABCDEF" | ||
26 | |||
27 | hexEncodeArray :: Array Word8 Char | ||
28 | hexEncodeArray = array (0, 16) hexEncMap | ||
29 | |||
30 | hexDecodeMap :: M.Map Char Word8 | ||
31 | hexDecodeMap = M.fromList [(b, a) | (a, b) <- hexEncMap] | ||
32 | |||
33 | -- {{{1 toHex | ||
34 | toHex :: Word8 -> String | ||
35 | toHex o = let | ||
36 | hn = o `shiftR` 4 | ||
37 | ln = o .&. 0xf | ||
38 | in [hexEncodeArray ! hn, hexEncodeArray ! ln] | ||
39 | |||
40 | -- {{{1 fromHex | ||
41 | fromHex :: String -> Maybe Word8 | ||
42 | fromHex = let | ||
43 | dec [Just hn, Just ln] = let | ||
44 | o = hn `shiftL` 4 .|. ln | ||
45 | in Just o | ||
46 | dec _ = Nothing | ||
47 | in dec . map (flip M.lookup hexDecodeMap . toUpper) | ||
48 | |||
49 | -- {{{1 incremental coding | ||
50 | -- | Data type for the incremental encoding functions. | ||
51 | data EncIncData = EChunk [Word8] -- ^ a chunk of data to be encoded | ||
52 | | EDone -- ^ the signal to the encoder that the stream of data is ending | ||
53 | |||
54 | -- | Data type for the result of calling the incremental encoding functions. | ||
55 | data EncIncRes i = EPart i (EncIncData -> EncIncRes i) -- ^ a partial result together with the continuation to use for further encoding | ||
56 | | EFinal i -- ^ the final result of encoding (the response to 'EDone') | ||
57 | |||
58 | encoder f os = case f (EChunk os) of | ||
59 | EPart r1 f' -> case f' EDone of | ||
60 | EFinal r2 -> r1 ++ r2 | ||
61 | |||
62 | -- | Data type for the incremental decoding functions. | ||
63 | data DecIncData i = DChunk i -- ^ a chunk of data to be decoded | ||
64 | | DDone -- ^ the signal to the decoder that the stream of data is ending | ||
65 | |||
66 | -- | Data type for the result of calling the incremental encoding functions. | ||
67 | data DecIncRes i = DPart [Word8] (DecIncData i -> DecIncRes i) -- ^ a partial result together with the continuation to user for further decoding | ||
68 | | DFinal [Word8] i -- ^ the final result of decoding (the response to 'DDone') | ||
69 | | DFail [Word8] i -- ^ a partial result for a failed decoding, together with the remainder of the data passed in so far | ||
70 | |||
71 | decoder :: (DecIncData i -> DecIncRes i) -> i -> Maybe [Word8] | ||
72 | decoder f s = let | ||
73 | d = f (DChunk s) | ||
74 | in case d of | ||
75 | DFinal da _ -> Just da | ||
76 | DFail _ _ -> Nothing | ||
77 | DPart da f -> let | ||
78 | d' = f DDone | ||
79 | in case d' of | ||
80 | DFinal da' _ -> Just $ da ++ da' | ||
81 | DFail _ _ -> Nothing | ||
82 | DPart _ _ -> Nothing -- should never happen | ||