blob: 2903d014d8dfb3d70fe92d30df4df4252f6d2cae [file] [log] [blame]
module TBinaryProtocol (TBinaryProtocol(..)) where
import Thrift
import Data.Bits
import Data.Int
import GHC.Exts
import GHC.Prim
import GHC.Word
import Control.Exception
data TBinaryProtocol a = TTransport a => TBinaryProtocol a
version_mask = 0xffff0000
version_1 = 0x80010000;
getByte i b= 255 .&. (shiftR i (8*b))
getBytes i 0 = []
getBytes i n = (toEnum (getByte i (n-1)) :: Char):(getBytes i (n-1))
floatBits :: Double -> Word64
floatBits (D# d#) = W64# (unsafeCoerce# d#)
floatOfBits :: Word64 -> Double
floatOfBits (W64# b#) = D# (unsafeCoerce# b#)
composeBytesH :: [Char] -> Int -> Word32
composeBytesH [] n = 0
composeBytesH (h:t) n = (shiftL (fromIntegral (fromEnum h) :: Word32) (8*n)) .|. (composeBytesH t (n-1))
compBytes :: [Char] -> Word32
compBytes b = composeBytesH b ((length b)-1)
composeBytes64H :: [Char] -> Int -> Word64
composeBytes64H [] n = 0
composeBytes64H (h:t) n = (shiftL (fromIntegral (fromEnum h) :: Word64) (8*n)) .|. (composeBytes64H t (n-1))
compBytes64 :: [Char] -> Word64
compBytes64 b = composeBytes64H b ((length b)-1)
instance Protocol TBinaryProtocol where
getTransport (TBinaryProtocol t) = t
writeBool (TBinaryProtocol tr) b = twrite tr (if b then [toEnum 1::Char] else [toEnum 0::Char])
writeByte (TBinaryProtocol tr) b = twrite tr (getBytes b 1)
writeI16 (TBinaryProtocol tr) b = twrite tr (getBytes b 2)
writeI32 (TBinaryProtocol tr) b = twrite tr (getBytes b 4)
writeI64 (TBinaryProtocol tr) b = twrite tr (getBytes b 8)
writeDouble (TBinaryProtocol tr) b = writeI64 (TBinaryProtocol tr) (fromIntegral (floatBits b) :: Int)
writeString (TBinaryProtocol tr) s = do twrite tr (getBytes (length s) 4)
twrite tr s
writeBinary = writeString
writeMessageBegin (TBinaryProtocol tr) (n,t,s) = do writeI32 (TBinaryProtocol tr) (version_1 .|. (fromEnum t))
writeString (TBinaryProtocol tr) n
writeI32 (TBinaryProtocol tr) s
writeMessageEnd (TBinaryProtocol tr) = return ()
writeStructBegin (TBinaryProtocol tr) s = return ()
writeStructEnd (TBinaryProtocol tr) = return ()
writeFieldBegin a (n,t,i) = do writeByte a (fromEnum t)
writeI16 a i
writeFieldEnd a = return ()
writeFieldStop a = writeByte a (fromEnum T_STOP)
writeMapBegin a (k,v,s) = do writeByte a (fromEnum k)
writeByte a (fromEnum v)
writeI32 a s
writeMapEnd a = return ()
writeListBegin a (t,s) = do writeByte a (fromEnum t)
writeI32 a s
writeListEnd a = return ()
writeSetBegin = writeListBegin
writeSetEnd a = return ()
readByte (TBinaryProtocol tr) = do b <- treadAll tr 1
return $ (fromIntegral (fromIntegral (compBytes b) :: Int8) :: Int)
readI16 (TBinaryProtocol tr) = do b <- treadAll tr 2
return $ (fromIntegral (fromIntegral (compBytes b) :: Int16) :: Int)
readI32 (TBinaryProtocol tr) = do b <- treadAll tr 4
return $ (fromIntegral (fromIntegral (compBytes b) :: Int32) :: Int)
readI64 (TBinaryProtocol tr) = do b <- treadAll tr 8
return $ (fromIntegral (fromIntegral (compBytes64 b) :: Int64) :: Int)
readDouble (TBinaryProtocol tr) = do b <- readI64 (TBinaryProtocol tr)
return $ floatOfBits (fromIntegral b :: Word64)
readBool (TBinaryProtocol tr) = do b <- readByte (TBinaryProtocol tr)
return $ b == 1
readString (TBinaryProtocol tr) = do l <- readI32 (TBinaryProtocol tr)
treadAll tr l
readBinary = readString
readMessageBegin (TBinaryProtocol tr) = do ver <- readI32 (TBinaryProtocol tr)
if (ver .&. version_mask /= version_1) then
throwDyn (ProtocolExn PE_BAD_VERSION "Missing version identifier")
else do
s <- readString (TBinaryProtocol tr)
sz <- readI32 (TBinaryProtocol tr)
return (s,toEnum (ver .&. 0xFF) :: Message_type,fromIntegral sz :: Int)
readMessageEnd (TBinaryProtocol tr) = return ()
readStructBegin (TBinaryProtocol tr) = return ""
readStructEnd (TBinaryProtocol tr) = return ()
readFieldBegin (TBinaryProtocol tr) = do t <- readByte (TBinaryProtocol tr)
if (toEnum t :: T_type) /= T_STOP then
do s <- readI16 (TBinaryProtocol tr)
return ("",toEnum t :: T_type,fromIntegral s :: Int)
else return ("",toEnum t :: T_type,0)
readFieldEnd (TBinaryProtocol tr) = return ()
readMapBegin a = do kt <- readByte a
vt <- readByte a
s <- readI32 a
return (toEnum kt :: T_type,toEnum vt :: T_type,fromIntegral s :: Int)
readMapEnd a = return ()
readListBegin a = do b <- readByte a
s <- readI32 a
return (toEnum b :: T_type,fromIntegral s :: Int)
readListEnd a = return ()
readSetBegin = readListBegin
readSetEnd = readListEnd