blob: 5f42db45de7fea06435cf067d389cbdf028d9246 [file] [log] [blame]
--
-- 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.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
-- TODO: we want to set headers without recreating client...
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 }
-- TODO: make it public once we have first transform implementation for Haskell
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