summaryrefslogtreecommitdiff
path: root/src/Codec/Binary/Util.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Codec/Binary/Util.hs')
-rw-r--r--src/Codec/Binary/Util.hs82
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.
7module Codec.Binary.Util
8 ( toHex
9 , fromHex
10 , EncIncData(..)
11 , EncIncRes(..)
12 , DecIncData(..)
13 , DecIncRes(..)
14 , encoder
15 , decoder
16 ) where
17
18import Data.Array
19import Data.Bits
20import Data.Char
21import Data.Word
22import qualified Data.Map as M
23
24-- {{{1 hex enc/dec assoc list and maps
25hexEncMap = zip [0..] "0123456789ABCDEF"
26
27hexEncodeArray :: Array Word8 Char
28hexEncodeArray = array (0, 16) hexEncMap
29
30hexDecodeMap :: M.Map Char Word8
31hexDecodeMap = M.fromList [(b, a) | (a, b) <- hexEncMap]
32
33-- {{{1 toHex
34toHex :: Word8 -> String
35toHex o = let
36 hn = o `shiftR` 4
37 ln = o .&. 0xf
38 in [hexEncodeArray ! hn, hexEncodeArray ! ln]
39
40-- {{{1 fromHex
41fromHex :: String -> Maybe Word8
42fromHex = 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.
51data 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.
55data 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
58encoder 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.
63data 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.
67data 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
71decoder :: (DecIncData i -> DecIncRes i) -> i -> Maybe [Word8]
72decoder 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