| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import Foundation |
| |
| public enum TMessageType: Int32 { |
| case call = 1 |
| case reply = 2 |
| case exception = 3 |
| case oneway = 4 |
| } |
| |
| public enum TType: Int32 { |
| case stop = 0 |
| case void = 1 |
| case bool = 2 |
| case i8 = 3 |
| case double = 4 |
| case i16 = 6 |
| case i32 = 8 |
| case i64 = 10 |
| case string = 11 |
| case `struct` = 12 |
| case map = 13 |
| case set = 14 |
| case list = 15 |
| case utf8 = 16 |
| //case utf16 = 17 |
| case uuid = 17 |
| } |
| |
| public protocol TProtocol { |
| var transport: TTransport { get set } |
| init(on transport: TTransport) |
| // Reading Methods |
| |
| func readMessageBegin() throws -> (String, TMessageType, Int32) |
| func readMessageEnd() throws |
| func readStructBegin() throws -> String |
| func readStructEnd() throws |
| func readFieldBegin() throws -> (String, TType, Int32) |
| func readFieldEnd() throws |
| func readMapBegin() throws -> (TType, TType, Int32) |
| func readMapEnd() throws |
| func readSetBegin() throws -> (TType, Int32) |
| func readSetEnd() throws |
| func readListBegin() throws -> (TType, Int32) |
| func readListEnd() throws |
| |
| func read() throws -> String |
| func read() throws -> Bool |
| func read() throws -> UInt8 |
| func read() throws -> Int8 |
| func read() throws -> Int16 |
| func read() throws -> Int32 |
| func read() throws -> Int64 |
| func read() throws -> Double |
| func read() throws -> Data |
| func read() throws -> UUID |
| |
| // Writing methods |
| |
| func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws |
| func writeMessageEnd() throws |
| func writeStructBegin(name: String) throws |
| func writeStructEnd() throws |
| func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws |
| func writeFieldStop() throws |
| func writeFieldEnd() throws |
| func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws |
| func writeMapEnd() throws |
| func writeSetBegin(elementType: TType, size: Int32) throws |
| func writeSetEnd() throws |
| func writeListBegin(elementType: TType, size: Int32) throws |
| func writeListEnd() throws |
| |
| func write(_ value: String) throws |
| func write(_ value: Bool) throws |
| func write(_ value: UInt8) throws |
| func write(_ value: Int8) throws |
| func write(_ value: Int16) throws |
| func write(_ value: Int32) throws |
| func write(_ value: Int64) throws |
| func write(_ value: Double) throws |
| func write(_ value: Data) throws |
| func write(_ value: UUID) throws |
| } |
| |
| public extension TProtocol { |
| func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws { |
| try writeFieldBegin(name: name, type: type, fieldID: id) |
| try value.write(to: self) |
| try writeFieldEnd() |
| } |
| |
| func validateValue(_ value: Any?, named name: String) throws { |
| if value == nil { |
| throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)") |
| } |
| } |
| |
| func readResultMessageBegin() throws { |
| let (_, type, _) = try readMessageBegin(); |
| if type == .exception { |
| let x = try readException() |
| throw x |
| } |
| return |
| } |
| |
| func readException() throws -> TApplicationError { |
| return try TApplicationError.read(from: self) |
| } |
| |
| func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws { |
| try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID) |
| try ex.write(to: self) |
| try writeMessageEnd() |
| } |
| |
| func skip(type: TType) throws { |
| switch type { |
| case .bool: _ = try read() as Bool |
| case .i8: _ = try read() as Int8 |
| case .i16: _ = try read() as Int16 |
| case .i32: _ = try read() as Int32 |
| case .i64: _ = try read() as Int64 |
| case .double: _ = try read() as Double |
| case .string: _ = try read() as String |
| case .uuid: _ = try read() as UUID |
| |
| case .struct: |
| _ = try readStructBegin() |
| while true { |
| let (_, fieldType, _) = try readFieldBegin() |
| if fieldType == .stop { |
| break |
| } |
| try skip(type: fieldType) |
| try readFieldEnd() |
| } |
| try readStructEnd() |
| |
| |
| case .map: |
| let (keyType, valueType, size) = try readMapBegin() |
| for _ in 0..<size { |
| try skip(type: keyType) |
| try skip(type: valueType) |
| } |
| try readMapEnd() |
| |
| |
| case .set: |
| let (elemType, size) = try readSetBegin() |
| for _ in 0..<size { |
| try skip(type: elemType) |
| } |
| try readSetEnd() |
| |
| case .list: |
| let (elemType, size) = try readListBegin() |
| for _ in 0..<size { |
| try skip(type: elemType) |
| } |
| try readListEnd() |
| |
| default: |
| throw TProtocolError(error: .invalidData, message: "Invalid data") |
| } |
| } |
| } |