Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/valpackett/SwiftCBOR
A CBOR implementation for Swift
https://github.com/valpackett/SwiftCBOR
binary-serialization cbor serialization swift
Last synced: 3 months ago
JSON representation
A CBOR implementation for Swift
- Host: GitHub
- URL: https://github.com/valpackett/SwiftCBOR
- Owner: valpackett
- License: unlicense
- Created: 2015-11-25T22:51:43.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2024-04-02T15:12:40.000Z (7 months ago)
- Last Synced: 2024-04-14T12:58:51.205Z (7 months ago)
- Topics: binary-serialization, cbor, serialization, swift
- Language: Swift
- Homepage:
- Size: 240 KB
- Stars: 124
- Watchers: 8
- Forks: 75
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
[![unlicense](https://img.shields.io/badge/un-license-green.svg?style=flat)](http://unlicense.org)
# SwiftCBOR
A [CBOR (RFC 7049 Concise Binary Object Representation)](http://cbor.io) 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.
- A fully cross-platform Swift 5.x package!
- `Codable` support!
- 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 :-)
- Literal convertibles are defined 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, maybe even correctly. Encoding Float16s are not supported (they do not exist in Swift).
- Memory efficiency of encoding needs tuning. (Encoding is not typically done in-place.)
- Encoding indefinite-length data is supported but you need to explicitly add open and close information to your streaming data.
- [cbor.me](http://cbor.me) is recommended for viewing your CBOR-encoded data.## Installation
There are many ways: Swift Package Manager, CocoaPods, git submodule...
The CocoaPod is [submitted by contributors](https://github.com/myfreeweb/SwiftCBOR/issues/7), updates can be delayed there.
Swift Package Manager is the recommended dependency manager.
## Decoding
```swift
import SwiftCBORlet 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")])
```To unwrap the decoded `CBOR` values, use [PATTERN MATCHING](https://alisoftware.github.io/swift/pattern-matching/2016/05/16/pattern-matching-4/)!!
## Encoding
Encoding a value returns an array of bytes, `[UInt8]`. You can encode with `CBOR.encode(myValue)` or `myValue.encode()`. Any type that conforms to the `CBOREncodable` protocol may be encoded. You can implement the `CBOREncodable` protocol for your types and then encode as usual.
```swift
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)
```Due to Swift's incomplete generics system, you cannot call `someArray.encode()` or `someDictionary.encode()`, but you can simply use `CBOR.encode(someArrayOrMap)` so long as your array items or map key and value types conform to `CBOREncodable`.
In some cases it may be necessary to create a `CBOR` intermediate representation before encoding. For example, if you want to encode an array or dictionary containing heterogeneous types, as is common for JSON-like objects, you can't use native Swift maps yet. You can implement `CBOREncodable` on your type that would build a `CBOR` value and encode that, or do the `CBOR` value thing without `CBOREncodable`.
The `CBOR` enum can be [expressed with literals](https://developer.apple.com/documentation/swift/initialization_with_literals), but note that variables are not literals, so you might have to call the constructors manually.
```swift
public protocol CBOREncodable {
func encode(options: CBOROptions) -> [UInt8]
}struct MyStruct: CBOREncodable {
var x: Int
var y: Stringpublic 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
```The `encode` function doesn't *have* to look like that. If you want to do something custom, like [preserving the order of map keys](https://github.com/myfreeweb/SwiftCBOR/issues/21), you can build the `[UInt8]` manually. Look at the [Encoder functions](https://github.com/myfreeweb/SwiftCBOR/blob/master/SwiftCBOR/CBOREncoder.swift) for inspiration.
### Encoding API
The current general-purpose API is listed below. When you need fine grained control over the type you are encoding, use the following.
```swift
func encode(_ value: T) -> [UInt8]
func encode(_ dict: [A: B]) -> [UInt8]// NOTE: Please see the note on encoding byte strings at the end of this readme.
func encode(_ 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(_ arr: [T]) -> [UInt8]
func encodeMap(_ map: [A: B]) -> [UInt8]
func encodeTagged(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]
```### Indefinite-length data
To encode indefinite length arrays, maps, strings, and byte strings, explicitly use the open- and close-stream CBOR values. In between these two values, use encoded array and map *chunks* with `CBOR.encodeArrayChunk` and `CBOR.encodeMapChunk`. Indefinite string and bytestrings can be encoded as normal (i.e. they don't need their own 'chunk' function).
```swift
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(_ chunk: [T]) -> [UInt8]
func encodeMapChunk(_ map: [A: B]) -> [UInt8]
```### Note on endian reversal
Finally, a technical note on encoding byte string when using the general purpose array encoder, `CBOR.encode(..)`. If the function parameter `asByteString` is true, then arrays of ALL types EXCEPT UInt8 will be have the raw bytes of each item reversed (but not the order of the items together) if the computer is little endian (CBOR uses big endian or network byte order). Arrays of UInt8, are considered to be already in network byte order.
## Contributing
By participating in this project you agree to follow the [Contributor Code of Conduct](https://contributor-covenant.org/version/1/4/).
[The list of contributors is available on GitHub](https://github.com/myfreeweb/SwiftCBOR/graphs/contributors).
## License
This is free and unencumbered software released into the public domain.
For more information, please refer to the `UNLICENSE` file or [unlicense.org](https://unlicense.org).