1-- Licensed to the Apache Software Foundation (ASF) under one
2-- or more contributor license agreements. See the NOTICE file
3-- distributed with this work for additional information
4-- regarding copyright ownership. The ASF licenses this file
5-- to you under the Apache License, Version 2.0 (the
6-- "License"); you may not use this file except in compliance
7-- with the License. You may obtain a copy of the License at
8--
9--   http://www.apache.org/licenses/LICENSE-2.0
10--
11-- Unless required by applicable law or agreed to in writing,
12-- software distributed under the License is distributed on an
13-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14-- KIND, either express or implied. See the License for the
15-- specific language governing permissions and limitations
16-- under the License.
17--
18
19{-# OPTIONS_GHC -fno-warn-orphans #-}
20
21module Thrift.Types where
22
23import Data.Foldable (foldl')
24import Data.Hashable ( Hashable, hashWithSalt )
25import Data.Int
26import Test.QuickCheck.Arbitrary
27import Test.QuickCheck.Gen (elements)
28import Data.Text.Lazy (Text)
29import qualified Data.ByteString.Lazy as LBS
30import qualified Data.HashMap.Strict as Map
31import qualified Data.HashSet as Set
32import qualified Data.Vector as Vector
33
34instance (Hashable a) => Hashable (Vector.Vector a) where
35  hashWithSalt = Vector.foldl' hashWithSalt
36
37
38type TypeMap = Map.HashMap Int16 (Text, ThriftType)
39
40data ThriftVal = TStruct (Map.HashMap Int16 (Text, ThriftVal))
41               | TMap ThriftType ThriftType [(ThriftVal, ThriftVal)]
42               | TList ThriftType [ThriftVal]
43               | TSet ThriftType [ThriftVal]
44               | TBool Bool
45               | TByte Int8
46               | TI16 Int16
47               | TI32 Int32
48               | TI64 Int64
49               | TString LBS.ByteString
50               | TBinary LBS.ByteString
51               | TDouble Double
52                 deriving (Eq, Show)
53
54-- Information is needed here for collection types (ie T_STRUCT, T_MAP,
55-- T_LIST, and T_SET) so that we know what types those collections are
56-- parameterized by.  In most protocols, this cannot be discerned directly
57-- from the data being read.
58data ThriftType
59    = T_STOP
60    | T_VOID
61    | T_BOOL
62    | T_BYTE
63    | T_DOUBLE
64    | T_I16
65    | T_I32
66    | T_I64
67    | T_STRING
68    | T_BINARY
69    | T_STRUCT TypeMap
70    | T_MAP ThriftType ThriftType
71    | T_SET ThriftType
72    | T_LIST ThriftType
73      deriving ( Eq, Show )
74
75-- NOTE: when using toEnum information about parametized types is NOT preserved.
76-- This design choice is consistent woth the Thrift implementation in other
77-- languages
78instance Enum ThriftType where
79    fromEnum T_STOP       = 0
80    fromEnum T_VOID       = 1
81    fromEnum T_BOOL       = 2
82    fromEnum T_BYTE       = 3
83    fromEnum T_DOUBLE     = 4
84    fromEnum T_I16        = 6
85    fromEnum T_I32        = 8
86    fromEnum T_I64        = 10
87    fromEnum T_STRING     = 11
88    fromEnum T_BINARY     = 11
89    fromEnum (T_STRUCT _) = 12
90    fromEnum (T_MAP _ _)  = 13
91    fromEnum (T_SET _)    = 14
92    fromEnum (T_LIST _)   = 15
93
94    toEnum 0  = T_STOP
95    toEnum 1  = T_VOID
96    toEnum 2  = T_BOOL
97    toEnum 3  = T_BYTE
98    toEnum 4  = T_DOUBLE
99    toEnum 6  = T_I16
100    toEnum 8  = T_I32
101    toEnum 10 = T_I64
102    toEnum 11 = T_STRING
103    -- toEnum 11 = T_BINARY
104    toEnum 12 = T_STRUCT Map.empty
105    toEnum 13 = T_MAP T_VOID T_VOID
106    toEnum 14 = T_SET T_VOID
107    toEnum 15 = T_LIST T_VOID
108    toEnum t = error $ "Invalid ThriftType " ++ show t
109
110data MessageType
111    = M_CALL
112    | M_REPLY
113    | M_EXCEPTION
114    | M_ONEWAY
115      deriving ( Eq, Show )
116
117instance Enum MessageType where
118    fromEnum M_CALL      =  1
119    fromEnum M_REPLY     =  2
120    fromEnum M_EXCEPTION =  3
121    fromEnum M_ONEWAY    =  4
122
123    toEnum 1 = M_CALL
124    toEnum 2 = M_REPLY
125    toEnum 3 = M_EXCEPTION
126    toEnum 4 = M_ONEWAY
127    toEnum t = error $ "Invalid MessageType " ++ show t
128
129instance Arbitrary MessageType where
130  arbitrary = elements [M_CALL, M_REPLY, M_EXCEPTION, M_ONEWAY]
131