blob: ed6db6fa3ea490dd83c4d3bb1f4c2fcf9855457d [file] [log] [blame]
Chris Simpsona9b6c702018-04-08 07:11:37 -04001/*
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
9*
10* http://www.apache.org/licenses/LICENSE-2.0
11*
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
17* under the License.
18*/
19
20import Foundation
Chris Simpsona9b6c702018-04-08 07:11:37 -040021
22public enum TMessageType: Int32 {
23 case call = 1
24 case reply = 2
25 case exception = 3
26 case oneway = 4
27}
28
29public enum TType: Int32 {
30 case stop = 0
31 case void = 1
32 case bool = 2
33 case i8 = 3
34 case double = 4
35 case i16 = 6
36 case i32 = 8
37 case i64 = 10
38 case string = 11
39 case `struct` = 12
40 case map = 13
41 case set = 14
42 case list = 15
Kino Roybaa0daa2022-10-21 00:20:35 -070043 case uuid = 16
Chris Simpsona9b6c702018-04-08 07:11:37 -040044}
45
46public protocol TProtocol {
47 var transport: TTransport { get set }
48 init(on transport: TTransport)
49 // Reading Methods
50
51 func readMessageBegin() throws -> (String, TMessageType, Int32)
52 func readMessageEnd() throws
53 func readStructBegin() throws -> String
54 func readStructEnd() throws
55 func readFieldBegin() throws -> (String, TType, Int32)
56 func readFieldEnd() throws
57 func readMapBegin() throws -> (TType, TType, Int32)
58 func readMapEnd() throws
59 func readSetBegin() throws -> (TType, Int32)
60 func readSetEnd() throws
61 func readListBegin() throws -> (TType, Int32)
62 func readListEnd() throws
63
64 func read() throws -> String
65 func read() throws -> Bool
66 func read() throws -> UInt8
Kino Roya9da9eb2022-10-07 23:13:01 -070067 func read() throws -> Int8
Chris Simpsona9b6c702018-04-08 07:11:37 -040068 func read() throws -> Int16
69 func read() throws -> Int32
70 func read() throws -> Int64
71 func read() throws -> Double
72 func read() throws -> Data
Kino Roya9da9eb2022-10-07 23:13:01 -070073 func read() throws -> UUID
74
Chris Simpsona9b6c702018-04-08 07:11:37 -040075 // Writing methods
76
77 func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws
78 func writeMessageEnd() throws
79 func writeStructBegin(name: String) throws
80 func writeStructEnd() throws
81 func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws
82 func writeFieldStop() throws
83 func writeFieldEnd() throws
84 func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws
85 func writeMapEnd() throws
86 func writeSetBegin(elementType: TType, size: Int32) throws
87 func writeSetEnd() throws
88 func writeListBegin(elementType: TType, size: Int32) throws
89 func writeListEnd() throws
90
91 func write(_ value: String) throws
92 func write(_ value: Bool) throws
93 func write(_ value: UInt8) throws
Kino Roya9da9eb2022-10-07 23:13:01 -070094 func write(_ value: Int8) throws
Chris Simpsona9b6c702018-04-08 07:11:37 -040095 func write(_ value: Int16) throws
96 func write(_ value: Int32) throws
97 func write(_ value: Int64) throws
98 func write(_ value: Double) throws
99 func write(_ value: Data) throws
Kino Roya9da9eb2022-10-07 23:13:01 -0700100 func write(_ value: UUID) throws
Chris Simpsona9b6c702018-04-08 07:11:37 -0400101}
102
103public extension TProtocol {
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800104 func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400105 try writeFieldBegin(name: name, type: type, fieldID: id)
106 try value.write(to: self)
107 try writeFieldEnd()
108 }
109
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800110 func validateValue(_ value: Any?, named name: String) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400111 if value == nil {
112 throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)")
113 }
114 }
115
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800116 func readResultMessageBegin() throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400117 let (_, type, _) = try readMessageBegin();
118 if type == .exception {
119 let x = try readException()
120 throw x
121 }
122 return
123 }
124
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800125 func readException() throws -> TApplicationError {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400126 return try TApplicationError.read(from: self)
127 }
128
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800129 func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400130 try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID)
131 try ex.write(to: self)
132 try writeMessageEnd()
133 }
134
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800135 func skip(type: TType) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400136 switch type {
137 case .bool: _ = try read() as Bool
Kino Roya9da9eb2022-10-07 23:13:01 -0700138 case .i8: _ = try read() as Int8
Chris Simpsona9b6c702018-04-08 07:11:37 -0400139 case .i16: _ = try read() as Int16
140 case .i32: _ = try read() as Int32
141 case .i64: _ = try read() as Int64
142 case .double: _ = try read() as Double
143 case .string: _ = try read() as String
Kino Roya9da9eb2022-10-07 23:13:01 -0700144 case .uuid: _ = try read() as UUID
Chris Simpsona9b6c702018-04-08 07:11:37 -0400145
146 case .struct:
147 _ = try readStructBegin()
148 while true {
149 let (_, fieldType, _) = try readFieldBegin()
150 if fieldType == .stop {
151 break
152 }
153 try skip(type: fieldType)
154 try readFieldEnd()
155 }
156 try readStructEnd()
157
158
159 case .map:
160 let (keyType, valueType, size) = try readMapBegin()
161 for _ in 0..<size {
162 try skip(type: keyType)
163 try skip(type: valueType)
164 }
165 try readMapEnd()
166
167
168 case .set:
169 let (elemType, size) = try readSetBegin()
170 for _ in 0..<size {
171 try skip(type: elemType)
172 }
173 try readSetEnd()
174
175 case .list:
176 let (elemType, size) = try readListBegin()
177 for _ in 0..<size {
178 try skip(type: elemType)
179 }
180 try readListEnd()
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500181
Chris Simpsona9b6c702018-04-08 07:11:37 -0400182 default:
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500183 throw TProtocolError(error: .invalidData, message: "Invalid data")
Chris Simpsona9b6c702018-04-08 07:11:37 -0400184 }
185 }
186}