Swift implementation of the Google Protocol Buffers VarInt specification
It is based on the Go implementation of the Google Protocol Buffers varint specification.
- Varints are a method of serializing integers using one or more bytes.
- Smaller numbers take a smaller number of bytes.
- Unsigned integers are serialized 7 bits at a time, starting with the least significant bits.
- The most significant bit (msb) in each output byte indicates if there is a continuation byte.
- Signed integers are mapped to unsigned integers using "zig-zag" encoding:
- Positive values x are written as 2*x + 0,
- Negative values x are written as 2*(~x) + 1
- So, negative values are complemented and whether to complement is encoded in bit 0.
Include the following dependency in your Package.swift file
let package = Package(
...
dependencies: [
...
.package(url: "https://github.com/swift-libp2p/swift-varint.git", .upToNextMajor(from: "0.0.1"))
],
...
)
import VarInt
/// Create some arbitrary data
let bytes = [UInt8]("Hello World".data(using: .utf8)!)
/// Prefix the bytes with their length so we can recover the data later
let uVarIntLengthPrefixedBytes = putUVarInt(UInt64(bytes.count)) + bytes
/// ... send the data across a network or something ...
/// Read the length prefixed data to determine the length of the payload
let lengthPrefix = uVarInt(uVarIntLengthPrefixedBytes)
print(lengthPrefix.value) // 11 -> `Hello World` == 11 bytes
print(lengthPrefix.bytesRead) // 1 -> The value `11` fits into 1 byte
/// So dropping the first byte will result in our original data again...
let recBytes = [UInt8](uVarIntLengthPrefixedBytes.dropFirst(lengthPrefix.bytesRead))
/// The original bytes and the recovered bytes are equal
print(bytes == recBytes) // True
/// Signed VarInts
public func putVarInt(_ value: Int64) -> [UInt8]
public func varInt(_ buffer: [UInt8]) -> DecodedVarInt // (value: Int64, bytesRead: Int)
/// Unsigned VarInts
public func putUVarInt(_ value: UInt64) -> [UInt8]
public func uVarInt(_ buffer: [UInt8]) -> DecodedUVarInt // (value: UInt64, bytesRead: Int)
Contributions are welcomed! This code is very much a proof of concept. I can guarantee you there's a better / safer way to accomplish the same results. Any suggestions, improvements, or even just critques, are welcome!
Let's make this code better together! 🤝
https://github.com/multiformats/go-varint
MIT © 2022 Breth Inc.