Rev 30 | Blame | Compare with Previous | Last modification | View Log | RSS feed
---- Licensed to the Apache Software Foundation (ASF) under one-- or more contributor license agreements. See the NOTICE file-- distributed with this work for additional information-- regarding copyright ownership. The ASF licenses this file-- to you under the Apache License, Version 2.0 (the-- "License"); you may not use this file except in compliance-- with the License. You may obtain a copy of the License at---- http://www.apache.org/licenses/LICENSE-2.0---- Unless required by applicable law or agreed to in writing,-- software distributed under the License is distributed on an-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY-- KIND, either express or implied. See the License for the-- specific language governing permissions and limitations-- under the License.--module Thrift.Protocol.Binary( module Thrift.Protocol, BinaryProtocol(..)) whereimport Control.Exception ( throw )import Data.Bitsimport Data.Intimport Data.List ( foldl' )import GHC.Extsimport GHC.Wordimport Thrift.Protocolimport Thrift.Transportversion_mask = 0xffff0000version_1 = 0x80010000data BinaryProtocol a = Transport a => BinaryProtocol ainstance Protocol BinaryProtocol wheregetTransport (BinaryProtocol t) = twriteMessageBegin p (n, t, s) = dowriteI32 p (version_1 .|. (fromEnum t))writeString p nwriteI32 p swriteMessageEnd _ = return ()writeStructBegin _ _ = return ()writeStructEnd _ = return ()writeFieldBegin p (_, t, i) = writeType p t >> writeI16 p iwriteFieldEnd _ = return ()writeFieldStop p = writeType p T_STOPwriteMapBegin p (k, v, n) = writeType p k >> writeType p v >> writeI32 p nwriteMapEnd p = return ()writeListBegin p (t, n) = writeType p t >> writeI32 p nwriteListEnd _ = return ()writeSetBegin p (t, n) = writeType p t >> writeI32 p nwriteSetEnd _ = return ()writeBool p b = tWrite (getTransport p) [toEnum $ if b then 1 else 0]writeByte p b = tWrite (getTransport p) (getBytes b 1)writeI16 p b = tWrite (getTransport p) (getBytes b 2)writeI32 p b = tWrite (getTransport p) (getBytes b 4)writeI64 p b = tWrite (getTransport p) (getBytes b 8)writeDouble p d = writeI64 p (fromIntegral $ floatBits d)writeString p s = writeI32 p (length s) >> tWrite (getTransport p) swriteBinary = writeStringreadMessageBegin p = dover <- readI32 pif (ver .&. version_mask /= version_1)then throw $ ProtocolExn PE_BAD_VERSION "Missing version identifier"else dos <- readString psz <- readI32 preturn (s, toEnum $ ver .&. 0xFF, sz)readMessageEnd _ = return ()readStructBegin _ = return ""readStructEnd _ = return ()readFieldBegin p = dot <- readType pn <- if t /= T_STOP then readI16 p else return 0return ("", t, n)readFieldEnd _ = return ()readMapBegin p = dokt <- readType pvt <- readType pn <- readI32 preturn (kt, vt, n)readMapEnd _ = return ()readListBegin p = dot <- readType pn <- readI32 preturn (t, n)readListEnd _ = return ()readSetBegin p = dot <- readType pn <- readI32 preturn (t, n)readSetEnd _ = return ()readBool p = (== 1) `fmap` readByte preadByte p = dobs <- tReadAll (getTransport p) 1return $ fromIntegral (composeBytes bs :: Int8)readI16 p = dobs <- tReadAll (getTransport p) 2return $ fromIntegral (composeBytes bs :: Int16)readI32 p = composeBytes `fmap` tReadAll (getTransport p) 4readI64 p = composeBytes `fmap` tReadAll (getTransport p) 8readDouble p = dobs <- readI64 preturn $ floatOfBits $ fromIntegral bsreadString p = readI32 p >>= tReadAll (getTransport p)readBinary = readString-- | Write a type as a bytewriteType :: (Protocol p, Transport t) => p t -> ThriftType -> IO ()writeType p t = writeByte p (fromEnum t)-- | Read a byte as though it were a ThriftTypereadType :: (Protocol p, Transport t) => p t -> IO ThriftTypereadType p = toEnum `fmap` readByte pcomposeBytes :: (Bits b, Enum t) => [t] -> bcomposeBytes = (foldl' fn 0) . (map $ fromIntegral . fromEnum)where fn acc b = (acc `shiftL` 8) .|. bgetByte :: Bits a => a -> Int -> agetByte i n = 255 .&. (i `shiftR` (8 * n))getBytes :: (Bits a, Integral a) => a -> Int -> StringgetBytes i 0 = []getBytes i n = (toEnum $ fromIntegral $ getByte i (n-1)):(getBytes i (n-1))floatBits :: Double -> Word64floatBits (D# d#) = W64# (unsafeCoerce# d#)floatOfBits :: Word64 -> DoublefloatOfBits (W64# b#) = D# (unsafeCoerce# b#)