SwiftCBOR 0.4.7

SwiftCBOR 0.4.7

维护者:Bryce HammondHamilton Chapman



SwiftCBOR 0.4.7

  • Val 和 Ham

unlicense

SwiftCBOR

Swift 的一个 RBOR (RFC 7049 简洁二进制对象表示) 解码器和编码器。可以直 接从 Swift 类型编码,或使用包装对象。解码到可以像原生 Swift 下标一样访问并使用等效字面符号表 达的 CBOR 值类型。

  • 一个全平台的 Swift 5.x 包!
  • Codable 支持!
  • 负整数以 NegativeInt(UInt) 解码,其中实际数字为 -1 - i(CBOR 的负整数可能会超过 64 位有符号整数)。
  • 会解码标签,但不处理。标签值编码,但不类型检查。自己做吧 :)
  • CBOR 类型定义了字面量可转换。
  • 以及 下标。所以您可以像这样访问 CBOR 映射和数组:myDecodedObject["numbers"][1]
  • 如果您要从流解码,请在实际流上实现 CBORInputStream 协议,并创建解码器,如下所示:CBORDecoder(stream: yourStream)
  • 半精度浮点数可以解码成 Float,可能甚至会正确。不支持编码 Float16(Swift 中不存在)。
  • 编码的内存效率需要调整。(通常编码不就地执行。)
  • 支持编码不定长数据,但您需要显式地将打开和关闭信息添加到您的流数据中。
  • 建议使用 cbor.me 来查看您的 CBOR 编码数据。

安装

有多种方式:Swift 包管理器、CocoaPods、git 子模块...

CocoaPod 是由贡献者提交的,那里可能有延迟更新。

Swift 包管理器是推荐的依赖项管理器。

解码

import SwiftCBOR

let decoded = try! CBOR.decode([0x9f, 0x18, 255, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2, 0x18, 1, 0x79, 0x00, 3, 0x41, 0x42, 0x43, 0x79, 0x00, 3, 0x41, 0x42, 0x43, 0xff])
print(decoded)
// CBOR.array([CBOR.unsignedInt(255), CBOR.array([CBOR.unsignedInt(1), CBOR.utf8String("ABC")]), CBOR.utf8String("ABC")])

要解包解码的 CBOR 值,请使用模式匹配!!

编码

编码值返回字节数组,[UInt8]。您可以使用CBOR.encode(myValue)myValue.encode()进行编码。任何符合CBOREncodable协议的类型都可以进行编码。您可以为您的类型实现CBOREncodable协议,然后按常规进行编码。

CBOR.encode(100)  // --> [0x18, 0x64] of type [UInt8]
Int(100).encode() // --> [0x18, 0x64]. Int conforms to the CBOREncodable protocol
"hello".encode()  // --> [0x65, 0x68, 0x65, 0x6c, 0x6c, 0x6f]. So does String
CBOR.encode(["a", "b", "c"])

let byteString: [UInt8] = [0x01, 0x02]
CBOR.encode(byteString, asByteString: true)

由于Swift的泛型系统不完整,您不能调用someArray.encode()someDictionary.encode(),但只要您的数组项目或映射键和值类型符合CBOREncodable,就可以使用CBOR.encode(someArrayOrMap)

在某些情况下,在编码之前可能需要创建一个CBOR中间表示形式。例如,如果您想编码包含异构类型的数组或字典(如JSON类似的对象),则还不能使用原生Swift映射。您可以为会构建CBOR值并对其进行编码的您的类型实现CBOREncodable,或者不使用CBOREncodable完成CBOR值的工作。

CBOR枚举可以用字面量表示,但请注意,变量不是字面量,因此您可能需要手动调用构造函数。

public protocol CBOREncodable {
    func encode(options: CBOROptions) -> [UInt8]
}

struct MyStruct: CBOREncodable {
    var x: Int
    var y: String

    public func encode(options: CBOROptions = CBOROption()) -> [UInt8] {
        let cborWrapper: CBOR = [
            "x": CBOR(integerLiteral: self.x), // You can use the literal constructors
            "y": CBOR.utf8String(self.y), // Or the enum variants
            "z": 123 // Or literals
        ]
        return cborWrapper.encode()
    }
}

MyStruct(x: 42, y: "words").encode()
// --> bytes (as hex): a2 61 79 65 77 6f 72 64 73 61 78 18 2a

encode函数不需要看起来那么复杂。如果您想进行自定义操作,例如保留映射键的顺序,您可以手动构建[UInt8]。查看编码器函数以获取灵感。

编码API

以下列出了当前通用API。当您需要对要编码的类型有更精细的控制时,请使用以下方式。

func encode<T: CBOREncodable>(_ value: T) -> [UInt8]
func encode<A: CBOREncodable, B: CBOREncodable>(_ dict: [A: B]) -> [UInt8]

// NOTE: Please see the note on encoding byte strings at the end of this readme.
func encode<T: CBOREncodable>(_ array: [T], asByteString: Bool = false) -> [UInt8]

/// Only needed for fine-grained control:
func encodeUInt{8, 16, 32, 64}(_ x: UInt8) -> [UInt8]
func encodeNegativeInt(_ x: Int) -> [UInt8]
func encodeByteString(_ bs: [UInt8]) -> [UInt8] // does no endian interpretation
func encodeString(_ str: String) -> [UInt8]
func encodeArray<T: CBOREncodable>(_ arr: [T]) -> [UInt8]
func encodeMap<A: CBOREncodable, B: CBOREncodable>(_ map: [A: B]) -> [UInt8]
func encodeTagged<T: CBOREncodable>(tag: UInt8, value: T) -> [UInt8]
func encodeSimpleValue(_ x: UInt8) -> [UInt8]
func encode{Null, Undefined, Break}() -> [UInt8]
func encodeFloat(_ x: Float) -> [UInt8]
func encodeDouble(_ x: Double) -> [UInt8]
func encodeBool(_ x: Bool) -> [UInt8]

不定长度数据

为了对不定长数组、映射、字符串和字节字符串进行编码,请显式使用开放和关闭流的CBOR值。在这两个值之间,使用编码后的数组和映射,通过CBOR.encodeArrayChunkCBOR.encodeMapChunk进行编码。不定长字符串和字节字符串可以按照常规方式进行编码(即不需要使用自己的“块”函数)。

let map: [String: Int] = ["a": 1]
let map2 = ["B": 2]
CBOR.encodeMapStreamStart() + CBOR.encodeMapChunk(map) + CBOR.encodeMapChunk(map2) + CBOR.encodeStreamEnd()

let bs: [UInt8] = [0xf0]
let bs2: [UInt8] = [0xff]
CBOR.encodeByteStringStreamStart()
    + CBOR.encode(bs, asByteString: true)
    + CBOR.encode(bs2, asByteString: true)
    + CBOR.encodeStreamEnd()

// Current stream-encoding API:
func encodeArrayStreamStart() -> [UInt8]
func encodeMapStreamStart() -> [UInt8]
func encodeStringStreamStart() -> [UInt8]
func encodeByteStringStreamStart() -> [UInt8]
func encodeStreamEnd() -> [UInt8] // Equal to CBOR.encodeBreak()
func encodeArrayChunk<T: CBOREncodable>(_ chunk: [T]) -> [UInt8]
func encodeMapChunk<A: CBOREncodable, B: CBOREncodable>(_ map: [A: B]) -> [UInt8]

关于端序反转的说明

最后,关于使用通用数组编码器CBOR.encode(..)进行字节字符串编码的技术说明。如果函数参数asByteString为true,则除 UInt8类型外的所有类型的数组将反转每个项目的原始字节(但不会改变项目顺序),如果计算机是小端字节序(CBOR使用大端或网络字节序)。UInt8数组被认为是已经处于网络字节序。

贡献

通过参与此项目,您同意遵守贡献者行为规范

贡献者名单可在GitHub上找到.

许可证

这是免费且无负担的软件,已发布到公共领域。更多信息,请参阅代码UNLICENSE文件或unlicense.org