| -- |
| -- 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 |
| |