CBOR 0.2.0

CBOR 0.2.0

Bryce Hammond 维护。



CBOR 0.2.0

  • Greg

SwiftCBOR unlicense Carthage compatible

A CBOR (RFC 7049 Concise Binary Object Representation) decoder and encoder in Swift. Encode directly from Swift types or use a wrapper object. Decode to a CBOR value type that can be accessed with native Swift subscripting and expressed with the equivalent literal notation.

  • No Foundation dependency! Ready for the cross-platform future of Swift.
  • Configured as a universal iOS / OS X framework.
  • Negative integers are decoded as NegativeInt(UInt), where the actual number is -1 - i (CBOR's negative integers can be larger than 64-bit signed integers).
  • Tags are decoded, but not processed. Tagged values are encoded, but not type-checked. Do it yourself :-)
  • Definited for the CBOR type!
  • And subscript too. So you can access CBOR maps and arrays like this: myDecodedObject["numbers"][1].
  • If you want to decode from a stream, implement the CBORInputStream protocol on your stream and create the decoder like this: CBORDecoder(stream: yourStream).
  • Half floats can be decoded to a Float. Encoding Float16s are not supported (they do not exist in Swift).
  • Memory efficiency of encoding needs tuning. (Encoding is not typically done in-place.)
  • Supports encoding indefinite-length data, but you need to explicitly add open and close information to your streaming data.
  • cbor.me is recommended for viewing your CBOR-encoded data.

Installation

使用 Carthage

github "myfreeweb/SwiftCBOR"

或者将其添加为 Git 子模块。

解码

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")])

编码

编码一个值将返回一个字节数组,[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的映射。你可以实现你类型上的CBOREncodable协议,或者构建一个CBOR值然后编码那个值。

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

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

    public func encode() -> [UInt8] {
        let cborWrapper = CBOR(dictionaryLiteral:
            ("x", CBOR(integerLiteral: self.x)),
            ("y", CBOR(stringLiteral: self.y)))
        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

当前通用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之外的所有类型数组将翻转每个元素的原始字节(但不是元素的顺序),如果计算机是little endian(CBOR使用big endian或网络字节序)。ubyte8数组被认为是已经处于网络字节序。

贡献

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

贡献者名单可在GitHub上获取.

许可证

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