Sources/TwitterApacheThrift/MutableThriftCompactBinary.swift (68 lines of code) (raw):
// Copyright 2021 Twitter, Inc.
// Licensed under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0//
//
// MutableThriftCompactBinary.swift
// TwitterApacheThrift
//
// Created on 9/24/21.
// Copyright © 2021 Twitter. All rights reserved.
import CoreFoundation
import Foundation
class MutableThriftCompactBinary: MutableThriftBinary {
override func write(_ value: Int16) {
write(Int32(value))
}
override func write(_ value: Int32) {
let bytes = encodedUnsignedLEB(value: value.zigZag)
insert(data: bytes)
}
override func write(_ value: Int64) {
let bytes = encodedUnsignedLEB(value: value.zigZag)
insert(data: bytes)
}
override func write(_ value: Double) {
var bits = CFSwapInt64HostToLittle(value.bitPattern)
let buffer = withUnsafePointer(to: &bits) {
return Data(bytes: UnsafePointer<UInt8>(OpaquePointer($0)), count: MemoryLayout<UInt64>.size)
}
insert(data: buffer)
}
override func write(_ data: Data) {
let lengthBytes = encodedUnsignedLEB(value: Int32(data.count))
insert(data: lengthBytes)
insert(data: data)
}
override func writeFieldBegin(fieldType: ThriftType, fieldID: Int, previousId: Int) {
// check if we can use delta encoding for the field id
let diff = fieldID - previousId
if (fieldID > previousId) && (diff <= 15) {
// Write them together
write((UInt8(fieldID - previousId) << 4) | fieldType.compactValue)
} else {
// Write them separate
write(fieldType.compactValue)
super.write(Int16(fieldID.zigZag))
}
}
override func writeListMetadata(elementType: ThriftType, count: Int) {
if count < 15 {
write((UInt8(count) << 4) | elementType.compactValue)
} else {
write(0xF0 | elementType.compactValue)
insert(data: encodedUnsignedLEB(value: count))
}
}
override func writeMapMetadata(keyType: ThriftType, valueType: ThriftType, count: Int) {
if count == 0 {
write(UInt8(0))
return
}
insert(data: encodedUnsignedLEB(value: count))
write((keyType.compactValue << 4) | valueType.compactValue)
}
func encodedUnsignedLEB<T: BinaryInteger>(value: T) -> Data {
var value = value
var count = 0
var data = Data()
data.reserveCapacity(10)
repeat {
var byte = UInt8(value & 0x7F)
value = value >> 7
if value != 0 {
byte |= 0x80
}
data.append(byte)
count += 1
} while value != 0
return data
}
}