Native CBOR codec with type-safe combinators
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 98.5%
Dune 0.4%
Other 1.2%
24 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-cbor https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-cbor
git@git.recoil.org:gazagnaire.org/ocaml-cbor git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-cbor

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

cbor#

Type-safe CBOR codec combinators for OCaml, with GADT-based bidirectional maps and bytesrw streaming.

Overview#

cbor provides encoding and decoding of CBOR (RFC 8949) using a combinator-based approach inspired by Jsont. Define a codec once as a value of type 'a t and use it for both directions. Codecs compose from base types through objects, arrays, variants, tags, and recursive types.

Streaming I/O is built on bytesrw for zero-copy reading and writing. Path-aware error messages pinpoint decode failures (e.g., $.items[3].name: expected string, got integer).

Installation#

Install with opam:

$ opam install nox-cbor

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install nox-cbor

Usage#

open Cbor

(* Define a codec for a record type *)
type person = { name : string; age : int }

let person_codec =
  Codec.Map.(
    map (fun name age -> { name; age })
    |> mem "name" (fun p -> p.name) Codec.text
    |> mem "age" (fun p -> p.age) Codec.int
    |> seal)

(* Encode to CBOR bytes *)
let encoded = Cbor.to_string person_codec { name = "Alice"; age = 30 }

(* Decode from CBOR bytes *)
let () =
  match Cbor.of_string person_codec encoded with
  | Ok p -> Printf.printf "%s is %d\n" p.name p.age
  | Error e -> prerr_endline (Error.to_string e)

(* Streaming decode from a bytesrw reader *)
let stream_decode encoded =
  let reader = Bytesrw.Bytes.Reader.of_string encoded in
  match Cbor.of_reader person_codec reader with
  | Ok p -> Printf.printf "%s\n" p.name
  | Error e -> prerr_endline (Error.to_string e)

Variants and Tags#

open Cbor

type shape = Circle of float | Rect of float * float

let shape_codec =
  Codec.Variant.(variant [
    case 0 Codec.float (fun r -> Circle r)
      (function Circle r -> Some r | _ -> None);
    case 1 (Codec.tuple2 Codec.float Codec.float) (fun (w, h) -> Rect (w, h))
      (function Rect (w, h) -> Some (w, h) | _ -> None);
  ])

API Overview#

The combinator surface lives under Cbor.Codec, organized by RFC 8949 major type:

  • Major 0/1 — integers -- int, int32, int64, uint, uint32, uint64
  • Major 2 — byte string -- bytes
  • Major 3 — text string -- text
  • Major 4 — array -- array, array_of, tuple2, tuple3, tuple4
  • Major 5 — map -- assoc, text_map, int_map, Map (records by text key), Map_int (records by int key, COSE / CWT style)
  • Major 6 — tag -- tag, tag_opt
  • Major 7 — simple / float -- null, bool, float
  • Sum types -- Variant (tag-discriminated), Variant_key (singleton-map)
  • Transformations -- map, conv, const, nullable, option, number, fix
  • Queries -- mem, int_mem, nth

Top-level I/O lives in Cbor:

  • Cbor.of_string, Cbor.of_string_exn — decode from CBOR bytes
  • Cbor.to_string — encode to CBOR bytes
  • Cbor.of_reader, Cbor.to_writer — bytesrw streaming
  • Cbor.decode, Cbor.encode — bridges to Value.t
  • Cbor.update_mem, Cbor.delete_mem — patch operations on maps

References#

  • RFC 8949 -- Concise Binary Object Representation (CBOR)

Licence#

ISC License. See LICENSE.md for details.