Bryan Duxbury | e59a80f | 2010-09-20 15:21:37 +0000 | [diff] [blame] | 1 | {-# LANGUAGE DeriveDataTypeable #-} |
Bryan Duxbury | 0781f2b | 2009-04-07 23:29:42 +0000 | [diff] [blame] | 2 | -- |
| 3 | -- Licensed to the Apache Software Foundation (ASF) under one |
| 4 | -- or more contributor license agreements. See the NOTICE file |
| 5 | -- distributed with this work for additional information |
| 6 | -- regarding copyright ownership. The ASF licenses this file |
| 7 | -- to you under the Apache License, Version 2.0 (the |
| 8 | -- "License"); you may not use this file except in compliance |
| 9 | -- with the License. You may obtain a copy of the License at |
| 10 | -- |
| 11 | -- http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | -- |
| 13 | -- Unless required by applicable law or agreed to in writing, |
| 14 | -- software distributed under the License is distributed on an |
| 15 | -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 16 | -- KIND, either express or implied. See the License for the |
| 17 | -- specific language governing permissions and limitations |
| 18 | -- under the License. |
| 19 | -- |
| 20 | |
| 21 | module Thrift.Protocol |
| 22 | ( Protocol(..) |
| 23 | , skip |
| 24 | , MessageType(..) |
| 25 | , ThriftType(..) |
| 26 | , ProtocolExn(..) |
| 27 | , ProtocolExnType(..) |
| 28 | ) where |
| 29 | |
| 30 | import Control.Monad ( replicateM_, unless ) |
| 31 | import Control.Exception |
| 32 | |
| 33 | import Data.Typeable ( Typeable ) |
| 34 | import Data.Int |
| 35 | |
| 36 | import Thrift.Transport |
| 37 | |
| 38 | |
| 39 | data ThriftType |
| 40 | = T_STOP |
| 41 | | T_VOID |
| 42 | | T_BOOL |
| 43 | | T_BYTE |
| 44 | | T_DOUBLE |
| 45 | | T_I16 |
| 46 | | T_I32 |
| 47 | | T_I64 |
| 48 | | T_STRING |
| 49 | | T_STRUCT |
| 50 | | T_MAP |
| 51 | | T_SET |
| 52 | | T_LIST |
| 53 | deriving ( Eq ) |
| 54 | |
| 55 | instance Enum ThriftType where |
| 56 | fromEnum T_STOP = 0 |
| 57 | fromEnum T_VOID = 1 |
| 58 | fromEnum T_BOOL = 2 |
| 59 | fromEnum T_BYTE = 3 |
| 60 | fromEnum T_DOUBLE = 4 |
| 61 | fromEnum T_I16 = 6 |
| 62 | fromEnum T_I32 = 8 |
| 63 | fromEnum T_I64 = 10 |
| 64 | fromEnum T_STRING = 11 |
| 65 | fromEnum T_STRUCT = 12 |
| 66 | fromEnum T_MAP = 13 |
| 67 | fromEnum T_SET = 14 |
| 68 | fromEnum T_LIST = 15 |
| 69 | |
| 70 | toEnum 0 = T_STOP |
| 71 | toEnum 1 = T_VOID |
| 72 | toEnum 2 = T_BOOL |
| 73 | toEnum 3 = T_BYTE |
| 74 | toEnum 4 = T_DOUBLE |
| 75 | toEnum 6 = T_I16 |
| 76 | toEnum 8 = T_I32 |
| 77 | toEnum 10 = T_I64 |
| 78 | toEnum 11 = T_STRING |
| 79 | toEnum 12 = T_STRUCT |
| 80 | toEnum 13 = T_MAP |
| 81 | toEnum 14 = T_SET |
| 82 | toEnum 15 = T_LIST |
Bryan Duxbury | e59a80f | 2010-09-20 15:21:37 +0000 | [diff] [blame] | 83 | toEnum t = error $ "Invalid ThriftType " ++ show t |
Bryan Duxbury | 0781f2b | 2009-04-07 23:29:42 +0000 | [diff] [blame] | 84 | |
| 85 | data MessageType |
| 86 | = M_CALL |
| 87 | | M_REPLY |
| 88 | | M_EXCEPTION |
| 89 | deriving ( Eq ) |
| 90 | |
| 91 | instance Enum MessageType where |
| 92 | fromEnum M_CALL = 1 |
| 93 | fromEnum M_REPLY = 2 |
| 94 | fromEnum M_EXCEPTION = 3 |
| 95 | |
| 96 | toEnum 1 = M_CALL |
| 97 | toEnum 2 = M_REPLY |
| 98 | toEnum 3 = M_EXCEPTION |
Bryan Duxbury | e59a80f | 2010-09-20 15:21:37 +0000 | [diff] [blame] | 99 | toEnum t = error $ "Invalid MessageType " ++ show t |
Bryan Duxbury | 0781f2b | 2009-04-07 23:29:42 +0000 | [diff] [blame] | 100 | |
| 101 | |
| 102 | class Protocol a where |
| 103 | getTransport :: Transport t => a t -> t |
| 104 | |
| 105 | writeMessageBegin :: Transport t => a t -> (String, MessageType, Int) -> IO () |
| 106 | writeMessageEnd :: Transport t => a t -> IO () |
| 107 | |
| 108 | writeStructBegin :: Transport t => a t -> String -> IO () |
| 109 | writeStructEnd :: Transport t => a t -> IO () |
| 110 | writeFieldBegin :: Transport t => a t -> (String, ThriftType, Int) -> IO () |
| 111 | writeFieldEnd :: Transport t => a t -> IO () |
| 112 | writeFieldStop :: Transport t => a t -> IO () |
| 113 | writeMapBegin :: Transport t => a t -> (ThriftType, ThriftType, Int) -> IO () |
| 114 | writeMapEnd :: Transport t => a t -> IO () |
| 115 | writeListBegin :: Transport t => a t -> (ThriftType, Int) -> IO () |
| 116 | writeListEnd :: Transport t => a t -> IO () |
| 117 | writeSetBegin :: Transport t => a t -> (ThriftType, Int) -> IO () |
| 118 | writeSetEnd :: Transport t => a t -> IO () |
| 119 | |
| 120 | writeBool :: Transport t => a t -> Bool -> IO () |
| 121 | writeByte :: Transport t => a t -> Int -> IO () |
| 122 | writeI16 :: Transport t => a t -> Int -> IO () |
| 123 | writeI32 :: Transport t => a t -> Int -> IO () |
| 124 | writeI64 :: Transport t => a t -> Int64 -> IO () |
| 125 | writeDouble :: Transport t => a t -> Double -> IO () |
| 126 | writeString :: Transport t => a t -> String -> IO () |
| 127 | writeBinary :: Transport t => a t -> String -> IO () |
| 128 | |
| 129 | |
| 130 | readMessageBegin :: Transport t => a t -> IO (String, MessageType, Int) |
| 131 | readMessageEnd :: Transport t => a t -> IO () |
| 132 | |
| 133 | readStructBegin :: Transport t => a t -> IO String |
| 134 | readStructEnd :: Transport t => a t -> IO () |
| 135 | readFieldBegin :: Transport t => a t -> IO (String, ThriftType, Int) |
| 136 | readFieldEnd :: Transport t => a t -> IO () |
| 137 | readMapBegin :: Transport t => a t -> IO (ThriftType, ThriftType, Int) |
| 138 | readMapEnd :: Transport t => a t -> IO () |
| 139 | readListBegin :: Transport t => a t -> IO (ThriftType, Int) |
| 140 | readListEnd :: Transport t => a t -> IO () |
| 141 | readSetBegin :: Transport t => a t -> IO (ThriftType, Int) |
| 142 | readSetEnd :: Transport t => a t -> IO () |
| 143 | |
| 144 | readBool :: Transport t => a t -> IO Bool |
| 145 | readByte :: Transport t => a t -> IO Int |
| 146 | readI16 :: Transport t => a t -> IO Int |
| 147 | readI32 :: Transport t => a t -> IO Int |
| 148 | readI64 :: Transport t => a t -> IO Int64 |
| 149 | readDouble :: Transport t => a t -> IO Double |
| 150 | readString :: Transport t => a t -> IO String |
| 151 | readBinary :: Transport t => a t -> IO String |
| 152 | |
| 153 | |
| 154 | skip :: (Protocol p, Transport t) => p t -> ThriftType -> IO () |
Bryan Duxbury | e59a80f | 2010-09-20 15:21:37 +0000 | [diff] [blame] | 155 | skip _ T_STOP = return () |
| 156 | skip _ T_VOID = return () |
Bryan Duxbury | 0781f2b | 2009-04-07 23:29:42 +0000 | [diff] [blame] | 157 | skip p T_BOOL = readBool p >> return () |
| 158 | skip p T_BYTE = readByte p >> return () |
| 159 | skip p T_I16 = readI16 p >> return () |
| 160 | skip p T_I32 = readI32 p >> return () |
| 161 | skip p T_I64 = readI64 p >> return () |
| 162 | skip p T_DOUBLE = readDouble p >> return () |
| 163 | skip p T_STRING = readString p >> return () |
Bryan Duxbury | e59a80f | 2010-09-20 15:21:37 +0000 | [diff] [blame] | 164 | skip p T_STRUCT = do _ <- readStructBegin p |
Bryan Duxbury | 0781f2b | 2009-04-07 23:29:42 +0000 | [diff] [blame] | 165 | skipFields p |
| 166 | readStructEnd p |
| 167 | skip p T_MAP = do (k, v, s) <- readMapBegin p |
| 168 | replicateM_ s (skip p k >> skip p v) |
| 169 | readMapEnd p |
| 170 | skip p T_SET = do (t, n) <- readSetBegin p |
| 171 | replicateM_ n (skip p t) |
| 172 | readSetEnd p |
| 173 | skip p T_LIST = do (t, n) <- readListBegin p |
| 174 | replicateM_ n (skip p t) |
| 175 | readListEnd p |
| 176 | |
| 177 | |
| 178 | skipFields :: (Protocol p, Transport t) => p t -> IO () |
| 179 | skipFields p = do |
| 180 | (_, t, _) <- readFieldBegin p |
| 181 | unless (t == T_STOP) (skip p t >> readFieldEnd p >> skipFields p) |
| 182 | |
| 183 | |
| 184 | data ProtocolExnType |
| 185 | = PE_UNKNOWN |
| 186 | | PE_INVALID_DATA |
| 187 | | PE_NEGATIVE_SIZE |
| 188 | | PE_SIZE_LIMIT |
| 189 | | PE_BAD_VERSION |
| 190 | deriving ( Eq, Show, Typeable ) |
| 191 | |
| 192 | data ProtocolExn = ProtocolExn ProtocolExnType String |
| 193 | deriving ( Show, Typeable ) |
| 194 | instance Exception ProtocolExn |