Native CBOR codec with type-safe combinators
0
fork

Configure Feed

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

ocaml-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+45 -22
+28 -12
README.md
··· 17 17 18 18 ## Installation 19 19 20 + Install with opam: 21 + 22 + ```sh 23 + $ opam install cbor 20 24 ``` 21 - opam install cbor 25 + 26 + If opam cannot find the package, it may not yet be released in the public 27 + `opam-repository`. Add the overlay repository, then install it: 28 + 29 + ```sh 30 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 31 + $ opam update 32 + $ opam install cbor 22 33 ``` 23 34 24 35 ## Usage ··· 31 42 32 43 let person_codec = 33 44 let open Obj in 34 - let* name = mem "name" (fun p -> p.name) string in 35 - let* age = mem "age" (fun p -> p.age) int in 36 - return { name; age } |> finish 45 + seal 46 + (let* name = mem "name" (fun p -> p.name) string in 47 + let* age = mem "age" (fun p -> p.age) int in 48 + return { name; age }) 37 49 38 50 (* Encode to CBOR bytes *) 39 51 let encoded = encode_string person_codec { name = "Alice"; age = 30 } 40 52 41 53 (* Decode from CBOR bytes *) 42 - match decode_string person_codec encoded with 43 - | Ok p -> Printf.printf "%s is %d\n" p.name p.age 44 - | Error e -> prerr_endline (Error.to_string e) 54 + let () = 55 + match decode_string person_codec encoded with 56 + | Ok p -> Printf.printf "%s is %d\n" p.name p.age 57 + | Error e -> prerr_endline (Error.to_string e) 45 58 46 59 (* Streaming decode from a bytesrw reader *) 47 - let reader = Bytesrw.Bytes.Reader.of_string encoded in 48 - match decode person_codec reader with 49 - | Ok p -> Printf.printf "%s\n" p.name 50 - | Error e -> prerr_endline (Error.to_string e) 60 + let stream_decode encoded = 61 + let reader = Bytesrw.Bytes.Reader.of_string encoded in 62 + match decode person_codec reader with 63 + | Ok p -> Printf.printf "%s\n" p.name 64 + | Error e -> prerr_endline (Error.to_string e) 51 65 ``` 52 66 53 67 ### Variants and Tags 54 68 55 69 ```ocaml 70 + open Cbor 71 + 56 72 type shape = Circle of float | Rect of float * float 57 73 58 74 let shape_codec = ··· 70 86 - **`nullable`**, **`option`** -- Optional values 71 87 - **`array`**, **`array_of`**, **`tuple2`**--**`tuple4`** -- Array codecs 72 88 - **`assoc`**, **`string_map`**, **`int_map`** -- Map codecs 73 - - **`Obj`** module -- Record builder with string keys: `mem`, `mem_opt`, `mem_default`, `return`, `finish` 89 + - **`Obj`** module -- Record builder with string keys: `mem`, `mem_opt`, `mem_default`, `return`, `seal` 74 90 - **`Obj_int`** module -- Record builder with integer keys (COSE/CWT style) 75 91 - **`Variant`**, **`Variant_key`** -- Sum types via CBOR tags or string-keyed maps 76 92 - **`tag`**, **`tag_opt`** -- CBOR semantic tags
+1
cbor.opam
··· 22 22 "zarith" {>= "1.12"} 23 23 "odoc" {with-doc} 24 24 "alcobar" {with-test} 25 + "mdx" {with-test} 25 26 "loc" 26 27 ] 27 28 build: [
+4
dune
··· 8 8 ; Exclude specs (reference docs) from build 9 9 10 10 (data_only_dirs third_party specs) 11 + 12 + (mdx 13 + (files README.md) 14 + (libraries cbor bytesrw))
+2
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 (name cbor) 3 4 4 5 (generate_opam_files true) ··· 23 24 (zarith (>= 1.12)) 24 25 (odoc :with-doc) 25 26 (alcobar :with-test) 27 + (mdx :with-test) 26 28 loc))
+2 -2
lib/cbor.ml
··· 1069 1069 in 1070 1070 loop 0 1071 1071 1072 - let finish (m : ('o, 'o) mem) : 'o t = 1072 + let seal (m : ('o, 'o) mem) : 'o t = 1073 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 *) ··· 1396 1396 in 1397 1397 loop 0 1398 1398 1399 - let finish (m : ('o, 'o) mem) : 'o t = 1399 + let seal (m : ('o, 'o) mem) : 'o t = 1400 1400 let keys = member_keys m in 1401 1401 let kind = 1402 1402 Fmt.str "obj_int({%s})" (String.concat ", " (List.map string_of_int keys))
+4 -4
lib/cbor.mli
··· 197 197 val return : 'o -> ('o, 'o) mem 198 198 (** [return v] completes the object codec, returning the built value. *) 199 199 200 - val finish : ('o, 'o) mem -> 'o t 201 - (** [finish m] converts the member specification to a codec. *) 200 + val seal : ('o, 'o) mem -> 'o t 201 + (** [seal m] converts the member specification to a codec. *) 202 202 end 203 203 204 204 (** {1:int_objects Integer-Keyed Objects} ··· 226 226 val return : 'o -> ('o, 'o) mem 227 227 (** [return v] completes the codec. *) 228 228 229 - val finish : ('o, 'o) mem -> 'o t 230 - (** [finish m] converts to a codec. *) 229 + val seal : ('o, 'o) mem -> 'o t 230 + (** [seal m] converts to a codec. *) 231 231 end 232 232 233 233 (** {1:tags Tagged Values}
+2 -2
test/test_cbor.ml
··· 358 358 let* age = mem "age" snd Cbor.int in 359 359 return (name, age) 360 360 in 361 - let codec = finish codec in 361 + let codec = seal codec in 362 362 let v = ("Alice", 30) in 363 363 let encoded = Cbor.encode_string codec v in 364 364 let decoded = Cbor.decode_string_exn codec encoded in ··· 681 681 let* age = mem "age" snd Cbor.int in 682 682 return (name, age) 683 683 in 684 - let codec = Cbor.Obj.finish codec in 684 + let codec = Cbor.Obj.seal codec in 685 685 let k = Cbor.kind codec in 686 686 Alcotest.(check string) "obj kind" "obj({name, age})" k); 687 687 Alcotest.test_case "kind: query codecs" `Quick (fun () ->
+2 -2
test/test_value.ml
··· 497 497 type person = { name : string; age : int; email : string option } 498 498 499 499 let person_codec = 500 - Cbor.Obj.finish 500 + Cbor.Obj.seal 501 501 @@ 502 502 let open Cbor.Obj in 503 503 let* name = mem "name" (fun p -> p.name) Cbor.string in ··· 536 536 } 537 537 538 538 let cwt_claims_codec = 539 - Cbor.Obj_int.finish 539 + Cbor.Obj_int.seal 540 540 @@ 541 541 let open Cbor.Obj_int in 542 542 let* iss = mem_opt 1 (fun c -> c.iss) Cbor.string in