1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
-- |
-- 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
|