Native CBOR codec with type-safe combinators
0
fork

Configure Feed

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

json: rename mem -> member / finish -> seal across the codec + value API

Object combinators: [Object.mem] -> [Object.member], [Object.opt_mem]
-> [Object.opt_member], [Object.case_mem] -> [Object.case_member]. The
sibling submodules [Object.Mem] / [Object.Mems] become
[Object.Member] / [Object.Members]. RFC 8259 §4 calls these
"name/value pairs, referred to as the members", so mirror the spec
name rather than the shortened [mem].

[Object.finish] -> [Object.seal]. "Seal" reads as "close the map, no
more members added", which is what the operation does.

Value constructors/queries: [Value.mem] (function) -> [Value.member];
[Value.mem_find] -> [Value.member_key]; [Value.mem_names] ->
[Value.member_names]; [Value.mem_keys] -> [Value.member_keys].
[type mem = ...] -> [type member = ...]; [type object'] still points
at [member list].

Downstream (~80 files across slack, sbom, stripe, sigstore, requests,
claude, irmin, freebox) updated via perl-pie. dune build clean,
dune test ocaml-json clean.

+26 -20
+10 -6
cbor.opam
··· 5 5 Type-safe CBOR (RFC 8949) encoding and decoding using a combinator-based 6 6 approach. Define codecs once and use them for both encoding and decoding 7 7 OCaml values to and from CBOR binary format.""" 8 - maintainer: ["Anil Madhavapeddy <anil@recoil.org>"] 9 - authors: ["Anil Madhavapeddy"] 8 + maintainer: ["Thomas Gazagnaire <thomas@gazagnaire.org>"] 9 + authors: [ 10 + "Anil Madhavapeddy <anil@recoil.org>" 11 + "Thomas Gazagnaire <thomas@gazagnaire.org>" 12 + ] 10 13 license: "ISC" 11 14 tags: ["org:blacksun" "codec.binary"] 12 - homepage: "https://tangled.org/anil.recoil.org/ocaml-cbor" 13 - bug-reports: "https://tangled.org/anil.recoil.org/ocaml-cbor/issues" 15 + homepage: "https://tangled.org/gazagnaire.org/ocaml-cbor" 16 + bug-reports: "https://tangled.org/gazagnaire.org/ocaml-cbor/issues" 14 17 depends: [ 15 18 "dune" {>= "3.21"} 16 19 "ocaml" {>= "5.1"} ··· 18 21 "fmt" {>= "0.9"} 19 22 "zarith" {>= "1.12"} 20 23 "odoc" {with-doc} 21 - "crowbar" {>= "0.2" & with-test} 24 + "alcobar" {with-test} 25 + "loc" 22 26 ] 23 27 build: [ 24 28 ["dune" "subst"] {dev} ··· 34 38 "@doc" {with-doc} 35 39 ] 36 40 ] 37 - dev-repo: "git+https://tangled.org/anil.recoil.org/ocaml-cbor" 41 + dev-repo: "git+https://tangled.org/gazagnaire.org/ocaml-cbor" 38 42 x-maintenance-intent: ["(latest)"] 39 43 x-quality-build: "2026-04-15" 40 44 x-quality-fuzz: "2026-04-15"
+5 -4
dune-project
··· 4 4 (generate_opam_files true) 5 5 6 6 (license ISC) 7 - (authors "Anil Madhavapeddy") 8 - (maintainers "Anil Madhavapeddy <anil@recoil.org>") 9 - (source (tangled anil.recoil.org/ocaml-cbor)) 7 + (authors "Anil Madhavapeddy <anil@recoil.org>" "Thomas Gazagnaire <thomas@gazagnaire.org>") 8 + (maintainers "Thomas Gazagnaire <thomas@gazagnaire.org>") 9 + (source (tangled gazagnaire.org/ocaml-cbor)) 10 10 11 11 (package 12 12 (name cbor) ··· 22 22 (fmt (>= 0.9)) 23 23 (zarith (>= 1.12)) 24 24 (odoc :with-doc) 25 - (crowbar (and (>= 0.2) :with-test)))) 25 + (alcobar :with-test) 26 + loc))
+11 -10
lib/cbor.ml
··· 931 931 let acc = field name (codec.encode v) acc in 932 932 encode_mem o (cont v) acc 933 933 934 - let rec mem_names : type o a. (o, a) mem -> string list = function 934 + let rec member_names : type o a. (o, a) mem -> string list = function 935 935 | Return _ -> [] 936 936 | Mem { name; cont; _ } -> 937 937 (* We need a dummy value to get the continuation, but for names 938 938 we just use Obj.magic since we only inspect structure *) 939 - name :: mem_names (cont (Stdlib.Obj.magic ())) 939 + name :: member_names (cont (Stdlib.Obj.magic ())) 940 940 | Mem_opt { name; cont; _ } -> 941 - name :: mem_names (cont (Stdlib.Obj.magic ())) 941 + name :: member_names (cont (Stdlib.Obj.magic ())) 942 942 | Mem_default { name; cont; _ } -> 943 - name :: mem_names (cont (Stdlib.Obj.magic ())) 943 + name :: member_names (cont (Stdlib.Obj.magic ())) 944 944 945 945 (* Build a dispatch table from member name to a streaming decoder that 946 946 stores the typed result into a hashtable keyed by name. The stored ··· 1070 1070 loop 0 1071 1071 1072 1072 let finish (m : ('o, 'o) mem) : 'o t = 1073 - let names = mem_names m in 1073 + let names = member_names m in 1074 1074 let kind = Fmt.str "obj({%s})" (String.concat ", " names) in 1075 1075 (* Pre-build the dispatch table for streaming decode *) 1076 1076 let decoder_list = build_decoders m in ··· 1251 1251 let acc = field key (codec.encode v) acc in 1252 1252 encode_mem o (cont v) acc 1253 1253 1254 - let rec mem_keys : type o a. (o, a) mem -> int list = function 1254 + let rec member_keys : type o a. (o, a) mem -> int list = function 1255 1255 | Return _ -> [] 1256 - | Mem { key; cont; _ } -> key :: mem_keys (cont (Stdlib.Obj.magic ())) 1257 - | Mem_opt { key; cont; _ } -> key :: mem_keys (cont (Stdlib.Obj.magic ())) 1256 + | Mem { key; cont; _ } -> key :: member_keys (cont (Stdlib.Obj.magic ())) 1257 + | Mem_opt { key; cont; _ } -> 1258 + key :: member_keys (cont (Stdlib.Obj.magic ())) 1258 1259 | Mem_default { key; cont; _ } -> 1259 - key :: mem_keys (cont (Stdlib.Obj.magic ())) 1260 + key :: member_keys (cont (Stdlib.Obj.magic ())) 1260 1261 1261 1262 (* Build a dispatch table from integer key to a streaming decoder that 1262 1263 stores the typed result into a hashtable keyed by int. *) ··· 1396 1397 loop 0 1397 1398 1398 1399 let finish (m : ('o, 'o) mem) : 'o t = 1399 - let keys = mem_keys m in 1400 + let keys = member_keys m in 1400 1401 let kind = 1401 1402 Fmt.str "obj_int({%s})" (String.concat ", " (List.map string_of_int keys)) 1402 1403 in