-
Notifications
You must be signed in to change notification settings - Fork 0
/
TLData.hs
66 lines (57 loc) · 1.96 KB
/
TLData.hs
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
module TLData (
readString,
getVarInteger,
getVectorLong
) where
import qualified Data.ByteString as B
import Data.Binary.Get
import Data.Binary
import Data.ByteString.Char8 as C
import Data.Bits
getWord24le :: Get Int
getWord24le = do
a <- getWord8
b <- getWord8
c <- getWord8
let low = fromIntegral(a)
mid = fromIntegral(b) `shiftL` 8
hi = fromIntegral(c) `shiftL` 16
return $ low .|. mid .|. hi
getVarByteString :: Int -> Get ByteString
getVarByteString n
| n >= 254 = do
new_len <- getWord24le
actual <- getByteString new_len
let rem = mod (new_len + 4) 4
skip $ if rem > 0 then (4 - rem) else 0
return $ actual
| otherwise = do
actual <- getByteString n
let rem = mod (n + 1) 4
skip $ if rem > 0 then (4 - rem) else 0
return $ actual
readString :: Get String
readString = do
len <- getWord8
fmap C.unpack $ getVarByteString $ (fromIntegral len)
shiftVarInt :: (Int, Integer) -> Word8 -> (Int, Integer)
shiftVarInt (shift, acc) b = (shift - 1, (fromIntegral(b) `shiftL` (8 * shift)) .|. acc )
getVarInteger :: Get Integer
getVarInteger = do
len <- getWord8
raw_int <- getVarByteString $ fromIntegral len
let total_len = C.length raw_int
return $ snd $ B.foldl shiftVarInt (total_len - 1, 0) raw_int
vector_long_step :: Int -> Get [Integer]
vector_long_step step
| step == 0 = do
return $ []
| otherwise = do
item <- getWord64le
rest <- vector_long_step $ step-1
return (fromIntegral(item) : rest)
getVectorLong :: Get [Integer]
getVectorLong = do
constructor <- getWord32le
num <- getWord32le
vector_long_step $ fromIntegral num