2 -- Licensed to the Apache Software Foundation (ASF) under one
3 -- or more contributor license agreements. See the NOTICE file
4 -- distributed with this work for additional information
5 -- regarding copyright ownership. The ASF licenses this file
6 -- to you under the Apache License, Version 2.0 (the
7 -- "License"); you may not use this file except in compliance
8 -- with the License. You may obtain a copy of the License at
10 -- http://www.apache.org/licenses/LICENSE-2.0
12 -- Unless required by applicable law or agreed to in writing,
13 -- software distributed under the License is distributed on an
14 -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 -- KIND, either express or implied. See the License for the
16 -- specific language governing permissions and limitations
21 module Thrift.Protocol.Header
22 ( module Thrift.Protocol
30 , createHeaderProtocol
31 , createHeaderProtocol1
34 import Thrift.Protocol
35 import Thrift.Protocol.Binary
36 import Thrift.Protocol.JSON
37 import Thrift.Protocol.Compact
38 import Thrift.Transport
39 import Thrift.Transport.Header
41 import qualified Data.Map as Map
43 data ProtocolWrap = forall a. (Protocol a) => ProtocolWrap(a)
45 instance Protocol ProtocolWrap where
46 readByte (ProtocolWrap p) = readByte p
47 readVal (ProtocolWrap p) = readVal p
48 readMessage (ProtocolWrap p) = readMessage p
49 writeVal (ProtocolWrap p) = writeVal p
50 writeMessage (ProtocolWrap p) = writeMessage p
52 data HeaderProtocol i o = (Transport i, Transport o) => HeaderProtocol {
53 trans :: HeaderTransport i o,
54 wrappedProto :: IORef ProtocolWrap
57 createProtocolWrap :: Transport t => ProtocolType -> t -> ProtocolWrap
58 createProtocolWrap typ t =
60 TBinary -> ProtocolWrap $ BinaryProtocol t
61 TCompact -> ProtocolWrap $ CompactProtocol t
62 TJSON -> ProtocolWrap $ JSONProtocol t
64 createHeaderProtocol :: (Transport i, Transport o) => i -> o -> IO(HeaderProtocol i o)
65 createHeaderProtocol i o = do
66 t <- openHeaderTransport i o
67 pid <- readIORef $ protocolType t
68 proto <- newIORef $ createProtocolWrap pid t
69 return $ HeaderProtocol { trans = t, wrappedProto = proto }
71 createHeaderProtocol1 :: Transport t => t -> IO(HeaderProtocol t t)
72 createHeaderProtocol1 t = createHeaderProtocol t t
74 resetProtocol :: (Transport i, Transport o) => HeaderProtocol i o -> IO ()
76 pid <- readIORef $ protocolType $ trans p
77 writeIORef (wrappedProto p) $ createProtocolWrap pid $ trans p
79 getWrapped = readIORef . wrappedProto
81 setTransport :: (Transport i, Transport o) => HeaderProtocol i o -> HeaderTransport i o -> HeaderProtocol i o
82 setTransport p t = p { trans = t }
84 updateTransport :: (Transport i, Transport o) => HeaderProtocol i o -> (HeaderTransport i o -> HeaderTransport i o)-> HeaderProtocol i o
85 updateTransport p f = setTransport p (f $ trans p)
87 type Headers = Map.Map String String
89 -- TODO: we want to set headers without recreating client...
90 setHeader :: (Transport i, Transport o) => HeaderProtocol i o -> String -> String -> HeaderProtocol i o
91 setHeader p k v = updateTransport p $ \t -> t { writeHeaders = Map.insert k v $ writeHeaders t }
93 setHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers -> HeaderProtocol i o
94 setHeaders p h = updateTransport p $ \t -> t { writeHeaders = h }
96 -- TODO: make it public once we have first transform implementation for Haskell
97 setTransforms :: (Transport i, Transport o) => HeaderProtocol i o -> [TransformType] -> HeaderProtocol i o
98 setTransforms p trs = updateTransport p $ \t -> t { writeTransforms = trs }
100 setTransform :: (Transport i, Transport o) => HeaderProtocol i o -> TransformType -> HeaderProtocol i o
101 setTransform p tr = updateTransport p $ \t -> t { writeTransforms = tr:(writeTransforms t) }
103 getWriteHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers
104 getWriteHeaders = writeHeaders . trans
106 getHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> IO [(String, String)]
107 getHeaders = readIORef . headers . trans
109 getProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> IO ProtocolType
110 getProtocolType p = readIORef $ protocolType $ trans p
112 setProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> ProtocolType -> IO ()
113 setProtocolType p typ = do
114 typ0 <- getProtocolType p
118 tSetProtocol (trans p) typ
121 instance (Transport i, Transport o) => Protocol (HeaderProtocol i o) where
122 readByte p = tReadAll (trans p) 1
125 proto <- getWrapped p
129 tResetProtocol (trans p)
131 proto <- getWrapped p
135 proto <- getWrapped p
138 writeMessage p x f = do
139 proto <- getWrapped p
140 writeMessage proto x f