• Stars
    star
    127
  • Rank 282,790 (Top 6 %)
  • Language
    Swift
  • License
    The Unlicense
  • Created about 9 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A CBOR implementation for Swift

unlicense

SwiftCBOR

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.

  • 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 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, updates can be delayed there.

Swift Package Manager is the recommended dependency manager.

Decoding

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

To unwrap the decoded CBOR values, use PATTERN MATCHING!!

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.

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, but note that variables are not literals, so you might have to call the constructors manually.

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

The encode function doesn't have to look like that. If you want to do something custom, like preserving the order of map keys, you can build the [UInt8] manually. Look at the Encoder functions 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.

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]

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).

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]

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.

The list of contributors is available on GitHub.

License

This is free and unencumbered software released into the public domain. For more information, please refer to the UNLICENSE file or unlicense.org.

More Repositories

1

httpotion

[Deprecated because ibrowse is not maintained] HTTP client for Elixir (use Tesla please)
Elixir
725
star
2

systemstat

Rust library for getting system information | also on https://codeberg.org/valpackett/systemstat
Rust
564
star
3

awesome-gtk

List of awesome GTK (3/4) applications
534
star
4

freepass

[DEPRECATED] password manager thing
Rust
310
star
5

cssprefixer

[DEPRECATED] A tool that rewrites your CSS files, adding vendor-prefixed versions of CSS3 rules.
Python
191
star
6

zshuery

[DEPRECATED] Minimal zsh framework
Shell
145
star
7

galacritty

[Abandoned experiment] GTK terminal emulator based on Alacritty [USE WEZTERM!]
Rust
145
star
8

soundfixer

A WebExtension that lets you fix sound problems in e.g. YouTube videos
JavaScript
137
star
9

clj-http-fake

Helper for faking clj-http requests | now on https://codeberg.org/valpackett/clj-http-fake
126
star
10

evscript

A tiny sandboxed Dyon scripting environment for evdev input devices that lets you do e.g. xcape in Wayland | now on https://codeberg.org/valpackett/evscript
122
star
11

magicbane

A web framework that integrates Servant, EKG, fast-logger, wai-cli… | now on https://codeberg.org/valpackett/magicbane
120
star
12

unixbar

Rust library for creating output for UNIX-style desktop bars like i3bar/swaybar, dzen2, lemonbar | now on https://codeberg.org/valpackett/unixbar
119
star
13

secstr

Secure string library for Rust | now on https://codeberg.org/valpackett/secstr
97
star
14

django-mode

Django mode and snippets for Emacs
Emacs Lisp
96
star
15

markbox

[DEPRECATED] A blogging engine for Dropbox based on Markdown
Python
94
star
16

intero.nvim

Haskell+Neovim lightning fast autocompletion and other IDE functionality
Vim Script
79
star
17

ring-ratelimit

Rate limiting middleware for Clojure Ring | now on https://codeberg.org/valpackett/ring-ratelimit
79
star
18

octohipster

[UNMAINTAINED] A hypermedia REST HTTP API library for Clojure
Clojure
75
star
19

transmitter

A WebExtension for the Transmission BitTorrent client
JavaScript
75
star
20

ringfinger

[DEPRECATED] Fun, fast, secure web development on top of Clojure/Ring
Clojure
67
star
21

rxjava-http-tail

RxJava-based HTTP log following library | now on https://codeberg.org/valpackett/rxjava-http-tail
65
star
22

freshcerts

ACME certificate protocol (Let's Encrypt) proxy client with a dashboard and monitoring
Ruby
60
star
23

rusty-sandbox

A sandboxing library for Rust | now on https://codeberg.org/valpackett/rusty-sandbox
58
star
24

capsicumizer

Run anything (like full blown GTK apps) under Capsicum
C++
54
star
25

pcre-heavy

A Haskell regular expressions library that doesn't suck | now on https://codeberg.org/valpackett/pcre-heavy
52
star
26

sweetroll

A personal website / #indieweb engine [OLD VERSION]
Haskell
51
star
27

micro-panel

Admin panel for micropub and microformats2 | also on: https://codeberg.org/valpackett/micro-panel
JavaScript
45
star
28

filesortd

Rule-based file sorting (like Hazel) with a Ruby DSL
Ruby
38
star
29

interactor

A Rust library for simple (usually command-line) user interaction | now on https://codeberg.org/valpackett/interactor
33
star
30

sweetroll2

A powerful micro/blogging engine with IndieWeb features (abandoned)
Elixir
28
star
31

hs-duktape

Haskell bindings for a very compact embedded JavaScript engine | now on https://codeberg.org/valpackett/hs-duktape
23
star
32

clj-configurator

A powerful yet simple configuration library for Clojure | now on https://codeberg.org/valpackett/clj-configurator
22
star
33

sweetreaction

A collection of React macros for Sweet.js - Actually react is bad
JavaScript
20
star
34

443d

TLS with HTTP/2 proxying, demultiplexed with SSH, on your port 443
Go
19
star
35

neojamvm

JamVM (lightweight Java Virtual Machine) but built with CMake
C
18
star
36

eslint-plugin-pug

An ESLint plugin for linting inline scripts in Pug files
JavaScript
17
star
37

gitson

A simple document store library for Git + JSON. | now on https://codeberg.org/valpackett/gitson
17
star
38

soad

SOcket Activator/Deactivator: like inetd but not really | now on https://codeberg.org/valpackett/soad
16
star
39

numbernine

Attempt at a desktop shell and stuff; abandoned in favor of https://github.com/DankBSD/waysmoke
D
16
star
40

pysectools

A small Python library that contains various security things
Python
15
star
41

weston-rs

[UNMAINTAINED] Rust bindings to libweston(-desktop) of Weston, the reference Wayland compositor
Rust
15
star
42

tiny-nix-ipc

Minimal Rust wrapper for using sockets as IPC with file descriptor passing | now on https://codeberg.org/valpackett/tiny-nix-ipc
15
star
43

micloudfaker

Use Xiaomi qmi.powerstrip.v1 offline | now on https://codeberg.org/valpackett/micloudfaker
14
star
44

shmemfdrs

Rust crate that creates anonymous shared memory file descriptors for IPC using memfd/SHM_ANON/shm_open | now on https://github.com/valpackett/shmemfdrs
13
star
45

ergonice

69-key split mechanical keyboard (PCB, case, firmware) | now on https://codeberg.org/valpackett/ergonice
13
star
46

gosemver

Semantic Versioning parsing, sorting, constraints and output library for the Go language
Go
13
star
47

indieweb-components

VanillaJS-based Web Components for the IndieWeb
JavaScript
13
star
48

wai-cli

Command line runner for Wai apps (using Warp) with TLS, CGI, socket activation & graceful shutdown | now on https://codeberg.org/valpackett/wai-cli
12
star
49

microformats2-parser

A Microformats 2 parser for Haskell | now on https://codeberg.org/valpackett/microformats2-parser - GH used for Actions only
Haskell
12
star
50

mail2elasticsearch

Fast ElasticSearch indexer for MIME email
Go
12
star
51

xvmmgr

A simple tray icon program for integrating a UNIX system running on Hyper-V or VirtualBox into the Windows desktop
PowerShell
11
star
52

sandblast

C
10
star
53

clj-bonecp-url

Clojure wrapper for BoneCP (DEPRECATED) that also parses database URLs | now on https://codeberg.org/valpackett/clj-bonecp-url
10
star
54

colorhash256

Like Chroma-Hash, but with ANSI terminal colors | now on https://codeberg.org/valpackett/colorhash256
9
star
55

broccoli-webpack

A Broccoli plugin for webpack
JavaScript
9
star
56

docker-freebsd-cross

Docker image for cross-compiling to FreeBSD. With pkg!!
Dockerfile
9
star
57

rusterpassword

A Rust implementation of the Spectre / Master Password algorithm | now on https://codeberg.org/valpackett/rusterpassword
9
star
58

appnetdav

[DEPRECATED] A WebDAV proxy for the App.net File API
Ruby
8
star
59

pebble-music-library

Music library browser for the Pebble smartwatch.
Java
8
star
60

less-mode

Less major mode for Emacs
Emacs Lisp
8
star
61

rpi-touchscreen-mainline

Building 7" Official Raspberry Pi Touchscreen drivers on vanilla mainline Linux kernels
C
8
star
62

antigravity

Antigravity lets you share files through App.net from an Android device - Press F for App.net
Java
7
star
63

labs

experiments
JavaScript
7
star
64

classyclock

Class schedule watchface for the Pebble smartwatch
HTML
6
star
65

gazeta

[DEPRECATED] A publish-subscribe (PubSub) framework for Clojure and ClojureScript, based on core.async.
Clojure
6
star
66

conatra

Sinatra-style syntax for the Internet of Things (CoAP/CoRE, Arduino)
Arduino
6
star
67

mf2sql

PostgreSQL schema for storing microformats2 JSON objects
PLpgSQL
6
star
68

startproject

Simple project starter for Emacs
Emacs Lisp
6
star
69

mason-ry

A Polymer element / web component that wraps Masonry, a layout library
HTML
6
star
70

http-link-header

A Haskell library for the HTTP Link header as specified in RFC 5988 "Web Linking" | now on https://codeberg.org/valpackett/http-link-header
6
star
71

broccoli-source-map

A Broccoli plugin for inlining or extracting sourcemaps.
JavaScript
5
star
72

feedrobot

[DEPRECATED] RSS/Atom to App.net Private Messages bot
Ruby
5
star
73

es-module-devserver

Simple static server middleware with ES Module path resolution | now on https://codeberg.org/valpackett/es-module-devserver
5
star
74

damnx509

A simple CLI for managing a small X.509 Certificate Authority | now on https://codeberg.org/valpackett/damnx509
5
star
75

dankshell

Go to https://github.com/myfreeweb/numbernine instead
Rust
5
star
76

modx-uncacher

Smarter cache cleaning for MODX Revolution
PHP
5
star
77

codeflask-element

A micro code-editor in a Custom Element (v1)
JavaScript
5
star
78

weston-extra-dip

[UNMAINTAINED] A pack of plugins for the Weston compositor
C++
5
star
79

wideplate

A multi-column responsive/adaptive CSS layout starter kit
CSS
5
star
80

sellout

IndieAuth/Micropub for static (Zola+GitHub) websites, runnable on Lambda
Python
4
star
81

sweetbuild

A Sweet.js DSL for Broccoli, the best frontend asset pipeline.
JavaScript
4
star
82

XmlDocTable

C# XML Documentation to LaTeX table converter based on Roslyn
C#
4
star
83

attrsets

Rust proc macro for defining multiple variants of a struct/enum with different attribute annotations e.g. for multiple Serde serializations | now on https://codeberg.org/valpackett/attrsets
4
star
84

devd-rs

Rust crate for listening to FreeBSD devd's device attach-detach notifications | now on https://codeberg.org/valpackett/devd-rs
4
star
85

node-red-contrib-nut-ups

Node-RED node that gets UPS data via NUT (Network UPS Tools).
HTML
4
star
86

loginw

Generic setuid wrapper for Wayland compositors
Rust
4
star
87

pdfork

A Rust fork wrapper that uses process descriptors (pdfork) on FreeBSD and normal fork elsewhere. | now on https://codeberg.org/valpackett/pdfork
4
star
88

indieweb-algorithms

A collection of implementations of IndieWeb algorithms in Haskell | now on https://codeberg.org/valpackett/indieweb-algorithms
4
star
89

nitm

Nobody In The Middle – Test if a web page looks the same via different Tor circuits
Python
3
star
90

appvertise

[DEPRECATED] Experimental ad network based on App.net and Bitcoin
Ruby
3
star
91

usmc-kmod

FreeBSD Kernel module for doing ARMv8 Secure Monitor Calls from userspace | now on https://codeberg.org/valpackett/usmc-kmod
3
star
92

imgroll

Image optimizer and nice metadata extractor (with AWS Lambda support)
Rust
3
star
93

clj-dcss

A Clojure library for parsing and processing Dungeon Crawl Stone Soup data.
Clojure
3
star
94

webgradients

A tool for creating simple and smooth PNG linear gradients with plain HTTP requests. 2.0.
Go
3
star
95

crawllog

A webapp that posts your Dungeon Crawl Stone Soup game logs (morgue files) to your website using Micropub
Python
3
star
96

supportappnet

[DEPRECATED] App.net-based support/feedback (inspired by services like Get Satisfaction).
Ruby
3
star
97

libwebp-sys

Rust bindings to libwebp | now on https://codeberg.org/valpackett/libwebp-sys
Rust
3
star
98

broccoli-brotli

Broccoli extension to apply brotli compression
JavaScript
3
star
99

statusboardthings

My widgets for Panic's Status Board for iPad - Press F for Status Board
Factor
3
star
100

ex_http_link

An Elixir library for the HTTP Link header as specified in RFC 5988 "Web Linking" | now on https://codeberg.org/valpackett/ex_http_link
3
star