blob: 87e3bc5c11a536180360d557dfd0a293001de1bb [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
43 case utf8 = 16
Kino Roya9da9eb2022-10-07 23:13:01 -070044 //case utf16 = 17
45 case uuid = 17
Chris Simpsona9b6c702018-04-08 07:11:37 -040046}
47
48public protocol TProtocol {
49 var transport: TTransport { get set }
50 init(on transport: TTransport)
51 // Reading Methods
52
53 func readMessageBegin() throws -> (String, TMessageType, Int32)
54 func readMessageEnd() throws
55 func readStructBegin() throws -> String
56 func readStructEnd() throws
57 func readFieldBegin() throws -> (String, TType, Int32)
58 func readFieldEnd() throws
59 func readMapBegin() throws -> (TType, TType, Int32)
60 func readMapEnd() throws
61 func readSetBegin() throws -> (TType, Int32)
62 func readSetEnd() throws
63 func readListBegin() throws -> (TType, Int32)
64 func readListEnd() throws
65
66 func read() throws -> String
67 func read() throws -> Bool
68 func read() throws -> UInt8
Kino Roya9da9eb2022-10-07 23:13:01 -070069 func read() throws -> Int8
Chris Simpsona9b6c702018-04-08 07:11:37 -040070 func read() throws -> Int16
71 func read() throws -> Int32
72 func read() throws -> Int64
73 func read() throws -> Double
74 func read() throws -> Data
Kino Roya9da9eb2022-10-07 23:13:01 -070075 func read() throws -> UUID
76
Chris Simpsona9b6c702018-04-08 07:11:37 -040077 // Writing methods
78
79 func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws
80 func writeMessageEnd() throws
81 func writeStructBegin(name: String) throws
82 func writeStructEnd() throws
83 func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws
84 func writeFieldStop() throws
85 func writeFieldEnd() throws
86 func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws
87 func writeMapEnd() throws
88 func writeSetBegin(elementType: TType, size: Int32) throws
89 func writeSetEnd() throws
90 func writeListBegin(elementType: TType, size: Int32) throws
91 func writeListEnd() throws
92
93 func write(_ value: String) throws
94 func write(_ value: Bool) throws
95 func write(_ value: UInt8) throws
Kino Roya9da9eb2022-10-07 23:13:01 -070096 func write(_ value: Int8) throws
Chris Simpsona9b6c702018-04-08 07:11:37 -040097 func write(_ value: Int16) throws
98 func write(_ value: Int32) throws
99 func write(_ value: Int64) throws
100 func write(_ value: Double) throws
101 func write(_ value: Data) throws
Kino Roya9da9eb2022-10-07 23:13:01 -0700102 func write(_ value: UUID) throws
Chris Simpsona9b6c702018-04-08 07:11:37 -0400103}
104
105public extension TProtocol {
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800106 func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400107 try writeFieldBegin(name: name, type: type, fieldID: id)
108 try value.write(to: self)
109 try writeFieldEnd()
110 }
111
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800112 func validateValue(_ value: Any?, named name: String) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400113 if value == nil {
114 throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)")
115 }
116 }
117
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800118 func readResultMessageBegin() throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400119 let (_, type, _) = try readMessageBegin();
120 if type == .exception {
121 let x = try readException()
122 throw x
123 }
124 return
125 }
126
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800127 func readException() throws -> TApplicationError {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400128 return try TApplicationError.read(from: self)
129 }
130
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800131 func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400132 try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID)
133 try ex.write(to: self)
134 try writeMessageEnd()
135 }
136
Antoine Cœur08a6eb62019-07-08 18:42:09 +0800137 func skip(type: TType) throws {
Chris Simpsona9b6c702018-04-08 07:11:37 -0400138 switch type {
139 case .bool: _ = try read() as Bool
Kino Roya9da9eb2022-10-07 23:13:01 -0700140 case .i8: _ = try read() as Int8
Chris Simpsona9b6c702018-04-08 07:11:37 -0400141 case .i16: _ = try read() as Int16
142 case .i32: _ = try read() as Int32
143 case .i64: _ = try read() as Int64
144 case .double: _ = try read() as Double
145 case .string: _ = try read() as String
Kino Roya9da9eb2022-10-07 23:13:01 -0700146 case .uuid: _ = try read() as UUID
Chris Simpsona9b6c702018-04-08 07:11:37 -0400147
148 case .struct:
149 _ = try readStructBegin()
150 while true {
151 let (_, fieldType, _) = try readFieldBegin()
152 if fieldType == .stop {
153 break
154 }
155 try skip(type: fieldType)
156 try readFieldEnd()
157 }
158 try readStructEnd()
159
160
161 case .map:
162 let (keyType, valueType, size) = try readMapBegin()
163 for _ in 0..<size {
164 try skip(type: keyType)
165 try skip(type: valueType)
166 }
167 try readMapEnd()
168
169
170 case .set:
171 let (elemType, size) = try readSetBegin()
172 for _ in 0..<size {
173 try skip(type: elemType)
174 }
175 try readSetEnd()
176
177 case .list:
178 let (elemType, size) = try readListBegin()
179 for _ in 0..<size {
180 try skip(type: elemType)
181 }
182 try readListEnd()
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500183
Chris Simpsona9b6c702018-04-08 07:11:37 -0400184 default:
James E. King IIIdbc1f8d2019-02-14 16:46:38 -0500185 throw TProtocolError(error: .invalidData, message: "Invalid data")
Chris Simpsona9b6c702018-04-08 07:11:37 -0400186 }
187 }
188}