blob: dd5212d27fc96853eeac9e798db2224af8503d51 [file] [log] [blame]
iproctorff8eb922007-07-25 19:06:13 +00001module TBinaryProtocol (TBinaryProtocol(..)) where
2 import Thrift
3 import Data.Bits
4 import Data.Int
5 import GHC.Exts
6 import GHC.Prim
7 import GHC.Word
8 import Control.Exception
9
10 data TBinaryProtocol a = (TTransport a) => TBinaryProtocol a
11
12 version_mask = 0xffff0000
13 version_1 = 0x80010000;
14
15 getByte i b= 255 .&. (shiftR i (8*b))
16 getBytes i 0 = []
17 getBytes i n = (toEnum (getByte i (n-1)) :: Char):(getBytes i (n-1))
18
19 floatBits :: Double -> Word64
20 floatBits (D# d#) = W64# (unsafeCoerce# d#)
21
22 floatOfBits :: Word64 -> Double
23 floatOfBits (W64# b#) = D# (unsafeCoerce# b#)
24
25 composeBytesH :: [Char] -> Int -> Word32
26 composeBytesH [] n = 0
27 composeBytesH (h:t) n = (shiftL (fromIntegral (fromEnum h) :: Word32) (8*n)) .|. (composeBytesH t (n-1))
28 compBytes :: [Char] -> Word32
29 compBytes b = composeBytesH b ((length b)-1)
30
31 composeBytes64H :: [Char] -> Int -> Word64
32 composeBytes64H [] n = 0
33 composeBytes64H (h:t) n = (shiftL (fromIntegral (fromEnum h) :: Word64) (8*n)) .|. (composeBytes64H t (n-1))
34 compBytes64 :: [Char] -> Word64
35 compBytes64 b = composeBytes64H b ((length b)-1)
36 instance TTransport a => Protocol (TBinaryProtocol a) where
37 writeBool (TBinaryProtocol tr) b = twrite tr (if b then [toEnum 1::Char] else [toEnum 0::Char])
38 writeByte (TBinaryProtocol tr) b = twrite tr (getBytes b 1)
39 writeI16 (TBinaryProtocol tr) b = twrite tr (getBytes b 2)
40 writeI32 (TBinaryProtocol tr) b = twrite tr (getBytes b 4)
41 writeI64 (TBinaryProtocol tr) b = twrite tr (getBytes b 8)
42 writeDouble (TBinaryProtocol tr) b = writeI64 (TBinaryProtocol tr) (fromIntegral (floatBits b) :: Int)
43 writeString (TBinaryProtocol tr) s = do twrite tr (getBytes (length s) 4)
44 twrite tr s
45 writeBinary = writeString
46 writeMessageBegin (TBinaryProtocol tr) (n,t,s) = do writeI32 (TBinaryProtocol tr) (version_1 .|. (fromEnum t))
47 writeString (TBinaryProtocol tr) n
48 writeI32 (TBinaryProtocol tr) s
49 writeMessageEnd (TBinaryProtocol tr) = return ()
50 writeStructBegin (TBinaryProtocol tr) s = return ()
51 writeStructEnd (TBinaryProtocol tr) = return ()
52 writeFieldBegin a (n,t,i) = do writeByte a (fromEnum t)
53 writeI16 a i
54 writeFieldEnd a = return ()
55 writeFieldStop a = writeByte a (fromEnum T_STOP)
56 writeMapBegin a (k,v,s) = do writeByte a (fromEnum k)
57 writeByte a (fromEnum v)
58 writeI32 a s
59 writeMapEnd a = return ()
60 writeListBegin a (t,s) = do writeByte a (fromEnum t)
61 writeI32 a s
62 writeListEnd a = return ()
63 writeSetBegin = writeListBegin
64 writeSetEnd a = return ()
65 readByte (TBinaryProtocol tr) = do b <- treadAll tr 1
66 return $ (fromIntegral (fromIntegral (compBytes b) :: Int8) :: Int)
67 readI16 (TBinaryProtocol tr) = do b <- treadAll tr 2
68 return $ (fromIntegral (fromIntegral (compBytes b) :: Int16) :: Int)
69 readI32 (TBinaryProtocol tr) = do b <- treadAll tr 4
70 return $ (fromIntegral (fromIntegral (compBytes b) :: Int32) :: Int)
71 readI64 (TBinaryProtocol tr) = do b <- treadAll tr 8
72 return $ (fromIntegral (fromIntegral (compBytes64 b) :: Int64) :: Int)
73 readDouble (TBinaryProtocol tr) = do b <- readI64 (TBinaryProtocol tr)
74 return $ floatOfBits (fromIntegral b :: Word64)
75 readBool (TBinaryProtocol tr) = do b <- readByte (TBinaryProtocol tr)
76 return $ b == 1
77 readString (TBinaryProtocol tr) = do l <- readI32 (TBinaryProtocol tr)
78 treadAll tr l
79 readBinary = readString
80 readMessageBegin (TBinaryProtocol tr) = do ver <- readI32 (TBinaryProtocol tr)
81 if (ver .&. version_mask /= version_1) then
82 throwDyn (ProtocolExn PE_BAD_VERSION "Missing version identifier")
83 else do
84 s <- readString (TBinaryProtocol tr)
85 sz <- readI32 (TBinaryProtocol tr)
86 return (s,toEnum (ver .&. 0xFF) :: Message_type,fromIntegral sz :: Int)
87 readMessageEnd (TBinaryProtocol tr) = return ()
88 readStructBegin (TBinaryProtocol tr) = return ""
89 readStructEnd (TBinaryProtocol tr) = return ()
90 readFieldBegin (TBinaryProtocol tr) = do t <- readByte (TBinaryProtocol tr)
91 if (toEnum t :: T_type) /= T_STOP then
92 do s <- readI16 (TBinaryProtocol tr)
93 return ("",toEnum t :: T_type,fromIntegral s :: Int)
94 else return ("",toEnum t :: T_type,0)
95 readFieldEnd (TBinaryProtocol tr) = return ()
96 readMapBegin a = do kt <- readByte a
97 vt <- readByte a
98 s <- readI32 a
99 return (toEnum kt :: T_type,toEnum vt :: T_type,fromIntegral s :: Int)
100 readMapEnd a = return ()
101 readListBegin a = do b <- readByte a
102 s <- readI32 a
103 return (toEnum b :: T_type,fromIntegral s :: Int)
104 readListEnd a = return ()
105 readSetBegin = readListBegin
106 readSetEnd = readListEnd
107 pflush (TBinaryProtocol tr) = tflush tr
108
109
110