1 /* 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 20 import Foundation 21 22 public enum TMessageType: Int32 { 23 case call = 1 24 case reply = 2 25 case exception = 3 26 case oneway = 4 27 } 28 29 public 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 uuid = 16 44 } 45 46 public protocol TProtocol { 47 var transport: TTransport { get set } 48 init(on transport: TTransport) 49 // Reading Methods 50 readMessageBeginnull51 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 67 func read() throws -> Int8 68 func read() throws -> Int16 69 func read() throws -> Int32 70 func read() throws -> Int64 71 func read() throws -> Double 72 func read() throws -> Data 73 func read() throws -> UUID 74 75 // 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 94 func write(_ value: Int8) throws 95 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 100 func write(_ value: UUID) throws 101 } 102 103 public extension TProtocol { 104 func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws { 105 try writeFieldBegin(name: name, type: type, fieldID: id) 106 try value.write(to: self) 107 try writeFieldEnd() 108 } 109 110 func validateValue(_ value: Any?, named name: String) throws { 111 if value == nil { 112 throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)") 113 } 114 } 115 116 func readResultMessageBegin() throws { 117 let (_, type, _) = try readMessageBegin(); 118 if type == .exception { 119 let x = try readException() 120 throw x 121 } 122 return 123 } 124 125 func readException() throws -> TApplicationError { 126 return try TApplicationError.read(from: self) 127 } 128 129 func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws { 130 try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID) 131 try ex.write(to: self) 132 try writeMessageEnd() 133 } 134 135 func skip(type: TType) throws { 136 switch type { 137 case .bool: _ = try read() as Bool 138 case .i8: _ = try read() as Int8 139 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 144 case .uuid: _ = try read() as UUID 145 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() 181 182 default: 183 throw TProtocolError(error: .invalidData, message: "Invalid data") 184 } 185 } 186 } 187