diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift')
-rw-r--r-- | src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift b/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift new file mode 100644 index 000000000..85acce045 --- /dev/null +++ b/src/jaegertracing/thrift/lib/swift/Sources/TBinaryProtocol.swift @@ -0,0 +1,384 @@ +/* + * 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 struct TBinaryProtocolVersion { + static let version1 = Int32(bitPattern: 0x80010000) + static let versionMask = Int32(bitPattern: 0xffff0000) +} + +public class TBinaryProtocol: TProtocol { + public var messageSizeLimit: UInt32 = 0 + + public var transport: TTransport + + // class level properties for setting global config (useful for server in lieu of Factory design) + public static var strictRead: Bool = false + public static var strictWrite: Bool = true + + private var strictRead: Bool + private var strictWrite: Bool + + var currentMessageName: String? + var currentFieldName: String? + + + public convenience init(transport: TTransport, strictRead: Bool, strictWrite: Bool) { + self.init(on: transport) + self.strictRead = strictRead + self.strictWrite = strictWrite + } + + public required init(on transport: TTransport) { + self.transport = transport + self.strictWrite = TBinaryProtocol.strictWrite + self.strictRead = TBinaryProtocol.strictRead + } + + func readStringBody(_ size: Int) throws -> String { + + var data = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport read failed")) { + data = try self.transport.readAll(size: size) + } + + return String(data: data, encoding: String.Encoding.utf8) ?? "" + } + + /// Mark: - TProtocol + + public func readMessageBegin() throws -> (String, TMessageType, Int32) { + let size: Int32 = try read() + var messageName = "" + var type = TMessageType.exception + + if size < 0 { + let version = size & TBinaryProtocolVersion.versionMask + if version != TBinaryProtocolVersion.version1 { + throw TProtocolError(error: .badVersion(expected: "\(TBinaryProtocolVersion.version1)", + got: "\(version)")) + } + type = TMessageType(rawValue: Int32(size) & 0x00FF) ?? type + messageName = try read() + } else { + if strictRead { + let errorMessage = "Missing message version, old client? Message Name: \(currentMessageName ?? "")" + throw TProtocolError(error: .invalidData, + message: errorMessage) + } + if messageSizeLimit > 0 && size > Int32(messageSizeLimit) { + throw TProtocolError(error: .sizeLimit(limit: Int(messageSizeLimit), got: Int(size))) + } + + messageName = try readStringBody(Int(size)) + type = TMessageType(rawValue: Int32(try read() as UInt8)) ?? type + } + + let seqID: Int32 = try read() + return (messageName, type, seqID) + } + + public func readMessageEnd() throws { + return + } + + public func readStructBegin() throws -> String { + return "" + } + + public func readStructEnd() throws { + return + } + + public func readFieldBegin() throws -> (String, TType, Int32) { + + let fieldType = TType(rawValue: Int32(try read() as UInt8)) ?? TType.stop + var fieldID: Int32 = 0 + + if fieldType != .stop { + fieldID = Int32(try read() as Int16) + } + + return ("", fieldType, fieldID) + } + + public func readFieldEnd() throws { + return + } + + public func readMapBegin() throws -> (TType, TType, Int32) { + var raw = Int32(try read() as UInt8) + guard let keyType = TType(rawValue: raw) else { + throw TProtocolError(message: "Unknown value for keyType TType: \(raw)") + } + + raw = Int32(try read() as UInt8) + guard let valueType = TType(rawValue: raw) else { + throw TProtocolError(message: "Unknown value for valueType TType: \(raw)") + } + let size: Int32 = try read() + + return (keyType, valueType, size) + } + + public func readMapEnd() throws { + return + } + + public func readSetBegin() throws -> (TType, Int32) { + let raw = Int32(try read() as UInt8) + guard let elementType = TType(rawValue: raw) else { + throw TProtocolError(message: "Unknown value for elementType TType: \(raw)") + } + + let size: Int32 = try read() + + return (elementType, size) + } + + public func readSetEnd() throws { + return + } + + public func readListBegin() throws -> (TType, Int32) { + let raw = Int32(try read() as UInt8) + guard let elementType = TType(rawValue: raw) else { + throw TProtocolError(message: "Unknown value for elementType TType: \(raw)") + } + let size: Int32 = try read() + + return (elementType, size) + } + + public func readListEnd() throws { + return + } + + public func read() throws -> String { + let data: Data = try read() + guard let str = String.init(data: data, encoding: .utf8) else { + throw TProtocolError(error: .invalidData, message: "Couldn't encode UTF-8 from data read") + } + return str + } + + public func read() throws -> Bool { + return (try read() as UInt8) == 1 + } + + public func read() throws -> UInt8 { + var buff = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { + buff = try self.transport.readAll(size: 1) + } + return buff[0] + } + + public func read() throws -> Int16 { + var buff = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { + buff = try self.transport.readAll(size: 2) + } + var ret = Int16(buff[0] & 0xff) << 8 + ret |= Int16(buff[1] & 0xff) + return ret + } + + public func read() throws -> Int32 { + var buff = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { + buff = try self.transport.readAll(size: 4) + } + var ret = Int32(buff[0] & 0xff) << 24 + ret |= Int32(buff[1] & 0xff) << 16 + ret |= Int32(buff[2] & 0xff) << 8 + ret |= Int32(buff[3] & 0xff) + + return ret + } + + public func read() throws -> Int64 { + var buff = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { + buff = try self.transport.readAll(size: 8) + } + var ret = Int64(buff[0] & 0xff) << 56 + ret |= Int64(buff[1] & 0xff) << 48 + ret |= Int64(buff[2] & 0xff) << 40 + ret |= Int64(buff[3] & 0xff) << 32 + ret |= Int64(buff[4] & 0xff) << 24 + ret |= Int64(buff[5] & 0xff) << 16 + ret |= Int64(buff[6] & 0xff) << 8 + ret |= Int64(buff[7] & 0xff) + + return ret + } + + public func read() throws -> Double { + let val = try read() as Int64 + return Double(bitPattern: UInt64(bitPattern: val)) + } + + public func read() throws -> Data { + let size = Int(try read() as Int32) + var data = Data() + try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { + data = try self.transport.readAll(size: size) + } + + return data + } + + // Write methods + + public func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws { + if strictWrite { + let version = TBinaryProtocolVersion.version1 | Int32(messageType.rawValue) + try write(version) + try write(name) + try write(sequenceID) + } else { + try write(name) + try write(UInt8(messageType.rawValue)) + try write(sequenceID) + } + currentMessageName = name + } + + public func writeMessageEnd() throws { + currentMessageName = nil + } + + public func writeStructBegin(name: String) throws { + return + } + + public func writeStructEnd() throws { + return + } + + public func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws { + try write(UInt8(fieldType.rawValue)) + try write(Int16(fieldID)) + } + + public func writeFieldStop() throws { + try write(UInt8(TType.stop.rawValue)) + } + + public func writeFieldEnd() throws { + return + } + + public func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws { + try write(UInt8(keyType.rawValue)) + try write(UInt8(valueType.rawValue)) + try write(size) + } + + public func writeMapEnd() throws { + return + } + + public func writeSetBegin(elementType: TType, size: Int32) throws { + try write(UInt8(elementType.rawValue)) + try write(size) + } + + public func writeSetEnd() throws { + return + } + + public func writeListBegin(elementType: TType, size: Int32) throws { + try write(UInt8(elementType.rawValue)) + try write(size) + } + + public func writeListEnd() throws { + return + } + + public func write(_ value: String) throws { + try write(value.data(using: .utf8)!) + } + + public func write(_ value: Bool) throws { + let byteVal: UInt8 = value ? 1 : 0 + try write(byteVal) + } + + public func write(_ value: UInt8) throws { + let buff = Data([value]) + + try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { + try self.transport.write(data: buff) + } + } + + public func write(_ value: Int16) throws { + var buff = Data() + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) + try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { + try self.transport.write(data: buff) + } + } + + public func write(_ value: Int32) throws { + var buff = Data() + buff.append(Data([UInt8(0xff & (value >> 24))])) + buff.append(Data([UInt8(0xff & (value >> 16))])) + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) + + try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { + try self.transport.write(data: buff) + } + } + + public func write(_ value: Int64) throws { + var buff = Data() + buff.append(Data([UInt8(0xff & (value >> 56))])) + buff.append(Data([UInt8(0xff & (value >> 48))])) + buff.append(Data([UInt8(0xff & (value >> 40))])) + buff.append(Data([UInt8(0xff & (value >> 32))])) + buff.append(Data([UInt8(0xff & (value >> 24))])) + buff.append(Data([UInt8(0xff & (value >> 16))])) + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) + + try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { + try self.transport.write(data: buff) + } + } + + public func write(_ value: Double) throws { + // Notably unsafe, since Double and Int64 are the same size, this should work fine + try self.write(Int64(bitPattern: value.bitPattern)) + } + + public func write(_ data: Data) throws { + try write(Int32(data.count)) + + try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { + try self.transport.write(data: data) + } + } +} |