module Thrift.Protocol.Header
( module Thrift.Protocol
, HeaderProtocol(..)
, getProtocolType
, setProtocolType
, getHeaders
, getWriteHeaders
, setHeader
, setHeaders
, createHeaderProtocol
, createHeaderProtocol1
) where
import Thrift.Protocol
import Thrift.Protocol.Binary
import Thrift.Protocol.JSON
import Thrift.Protocol.Compact
import Thrift.Transport
import Thrift.Transport.Header
import Data.IORef
import qualified Data.Map as Map
data ProtocolWrap = forall a. (Protocol a) => ProtocolWrap(a)
instance Protocol ProtocolWrap where
readByte (ProtocolWrap p) = readByte p
readVal (ProtocolWrap p) = readVal p
readMessage (ProtocolWrap p) = readMessage p
writeVal (ProtocolWrap p) = writeVal p
writeMessage (ProtocolWrap p) = writeMessage p
data HeaderProtocol i o = (Transport i, Transport o) => HeaderProtocol {
trans :: HeaderTransport i o,
wrappedProto :: IORef ProtocolWrap
}
createProtocolWrap :: Transport t => ProtocolType -> t -> ProtocolWrap
createProtocolWrap typ t =
case typ of
TBinary -> ProtocolWrap $ BinaryProtocol t
TCompact -> ProtocolWrap $ CompactProtocol t
TJSON -> ProtocolWrap $ JSONProtocol t
createHeaderProtocol :: (Transport i, Transport o) => i -> o -> IO(HeaderProtocol i o)
createHeaderProtocol i o = do
t <- openHeaderTransport i o
pid <- readIORef $ protocolType t
proto <- newIORef $ createProtocolWrap pid t
return $ HeaderProtocol { trans = t, wrappedProto = proto }
createHeaderProtocol1 :: Transport t => t -> IO(HeaderProtocol t t)
createHeaderProtocol1 t = createHeaderProtocol t t
resetProtocol :: (Transport i, Transport o) => HeaderProtocol i o -> IO ()
resetProtocol p = do
pid <- readIORef $ protocolType $ trans p
writeIORef (wrappedProto p) $ createProtocolWrap pid $ trans p
getWrapped = readIORef . wrappedProto
setTransport :: (Transport i, Transport o) => HeaderProtocol i o -> HeaderTransport i o -> HeaderProtocol i o
setTransport p t = p { trans = t }
updateTransport :: (Transport i, Transport o) => HeaderProtocol i o -> (HeaderTransport i o -> HeaderTransport i o)-> HeaderProtocol i o
updateTransport p f = setTransport p (f $ trans p)
type Headers = Map.Map String String
setHeader :: (Transport i, Transport o) => HeaderProtocol i o -> String -> String -> HeaderProtocol i o
setHeader p k v = updateTransport p $ \t -> t { writeHeaders = Map.insert k v $ writeHeaders t }
setHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers -> HeaderProtocol i o
setHeaders p h = updateTransport p $ \t -> t { writeHeaders = h }
setTransforms :: (Transport i, Transport o) => HeaderProtocol i o -> [TransformType] -> HeaderProtocol i o
setTransforms p trs = updateTransport p $ \t -> t { writeTransforms = trs }
setTransform :: (Transport i, Transport o) => HeaderProtocol i o -> TransformType -> HeaderProtocol i o
setTransform p tr = updateTransport p $ \t -> t { writeTransforms = tr:(writeTransforms t) }
getWriteHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers
getWriteHeaders = writeHeaders . trans
getHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> IO [(String, String)]
getHeaders = readIORef . headers . trans
getProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> IO ProtocolType
getProtocolType p = readIORef $ protocolType $ trans p
setProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> ProtocolType -> IO ()
setProtocolType p typ = do
typ0 <- getProtocolType p
if typ == typ0
then return ()
else do
tSetProtocol (trans p) typ
resetProtocol p
instance (Transport i, Transport o) => Protocol (HeaderProtocol i o) where
readByte p = tReadAll (trans p) 1
readVal p tp = do
proto <- getWrapped p
readVal proto tp
readMessage p f = do
tResetProtocol (trans p)
resetProtocol p
proto <- getWrapped p
readMessage proto f
writeVal p v = do
proto <- getWrapped p
writeVal proto v
writeMessage p x f = do
proto <- getWrapped p
writeMessage proto x f