Native CBOR codec with type-safe combinators
0
fork

Configure Feed

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

cbor: split Sort into sort.ml

Move Sort out of cbor.ml into its own sort.ml at the top level. Sort is
a public type labelling error contexts and Loc.Path frames; inlining it
in cbor.ml hid that role.

Replace Sort.of_cbor with Value.sort, following json's convention
(Value converts into Sort, not the other way). Sort stays dependency-
free.

+96 -85
+1 -50
lib/cbor.ml
··· 6 6 open Bytesrw 7 7 module Binary = Binary 8 8 module Value = Value 9 - 10 - module Sort = struct 11 - type t = 12 - | Unsigned 13 - | Negative 14 - | Bytes 15 - | Text 16 - | Array 17 - | Map 18 - | Tag 19 - | Bool 20 - | Null 21 - | Undefined 22 - | Simple 23 - | Float 24 - 25 - let to_string = function 26 - | Unsigned -> "unsigned integer" 27 - | Negative -> "negative integer" 28 - | Bytes -> "byte string" 29 - | Text -> "text string" 30 - | Array -> "array" 31 - | Map -> "map" 32 - | Tag -> "tag" 33 - | Bool -> "boolean" 34 - | Null -> "null" 35 - | Undefined -> "undefined" 36 - | Simple -> "simple value" 37 - | Float -> "float" 38 - 39 - let pp ppf s = Format.pp_print_string ppf (to_string s) 40 - 41 - let of_cbor = function 42 - | Value.Int z -> if Z.sign z >= 0 then Unsigned else Negative 43 - | Value.Bytes _ -> Bytes 44 - | Value.Text _ -> Text 45 - | Value.Array _ -> Array 46 - | Value.Map _ -> Map 47 - | Value.Tag _ -> Tag 48 - | Value.Bool _ -> Bool 49 - | Value.Null -> Null 50 - | Value.Undefined -> Undefined 51 - | Value.Simple _ -> Simple 52 - | Value.Float _ -> Float 53 - 54 - let kinded ~kind s = 55 - if kind = "" then to_string s else kind ^ " " ^ to_string s 56 - 57 - let or_kind ~kind s = if kind <> "" then kind else to_string s 58 - end 9 + module Sort = Sort 59 10 60 11 module Error = struct 61 12 type path = segment list
+4 -35
lib/cbor.mli
··· 52 52 53 53 (** {1:sort Sorts} *) 54 54 55 + module Sort = Sort 55 56 (** Sorts of CBOR values, one per RFC 8949 major type (with major type 7 split 56 - into {!Bool} / {!Null} / {!Undefined} / {!Simple} / {!Float} by the 57 - simple-value sub-tag). *) 58 - module Sort : sig 59 - (** The sort of a CBOR value. *) 60 - type t = 61 - | Unsigned (** Unsigned integer (major type 0). *) 62 - | Negative (** Negative integer (major type 1). *) 63 - | Bytes (** Byte string (major type 2). *) 64 - | Text (** Text string (major type 3). *) 65 - | Array (** Array (major type 4). *) 66 - | Map (** Map (major type 5). *) 67 - | Tag (** Tagged data item (major type 6). *) 68 - | Bool (** Boolean simple values (20/21, major 7). *) 69 - | Null (** Null simple value (22, major 7). *) 70 - | Undefined (** Undefined simple value (23, major 7). *) 71 - | Simple (** Other simple value (major 7). *) 72 - | Float (** Floating-point (major 7 ieee). *) 73 - 74 - val to_string : t -> string 75 - (** [to_string sort] is a human-readable name for [sort]. *) 76 - 77 - val pp : Format.formatter -> t -> unit 78 - (** [pp] formats sorts. *) 79 - 80 - val of_cbor : Value.t -> t 81 - (** [of_cbor v] returns the sort of CBOR value [v]. Inspects [Z.sign] on 82 - {!Value.Int} to distinguish {!Unsigned} from {!Negative}. *) 83 - 84 - val kinded : kind:string -> t -> string 85 - (** [kinded ~kind s] is [kind ^ " " ^ to_string s] when [kind] is non-empty, 86 - otherwise {!to_string} [s]. *) 87 - 88 - val or_kind : kind:string -> t -> string 89 - (** [or_kind ~kind s] is [kind] when non-empty, otherwise {!to_string} [s]. *) 90 - end 57 + into {!Sort.Bool} / {!Sort.Null} / {!Sort.Undefined} / {!Sort.Simple} / 58 + {!Sort.Float} by the simple-value sub-tag). Labels used in structured error 59 + contexts and {!Loc.Path} frames. *) 91 60 92 61 (** {1:errors Errors} *) 93 62
+36
lib/sort.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + type t = 7 + | Unsigned 8 + | Negative 9 + | Bytes 10 + | Text 11 + | Array 12 + | Map 13 + | Tag 14 + | Bool 15 + | Null 16 + | Undefined 17 + | Simple 18 + | Float 19 + 20 + let to_string = function 21 + | Unsigned -> "unsigned integer" 22 + | Negative -> "negative integer" 23 + | Bytes -> "byte string" 24 + | Text -> "text string" 25 + | Array -> "array" 26 + | Map -> "map" 27 + | Tag -> "tag" 28 + | Bool -> "boolean" 29 + | Null -> "null" 30 + | Undefined -> "undefined" 31 + | Simple -> "simple value" 32 + | Float -> "float" 33 + 34 + let pp ppf s = Format.pp_print_string ppf (to_string s) 35 + let kinded ~kind s = if kind = "" then to_string s else kind ^ " " ^ to_string s 36 + let or_kind ~kind s = if kind <> "" then kind else to_string s
+38
lib/sort.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + (** CBOR value sorts, used as labels in error contexts and {!Loc.Path} frames. 7 + 8 + A {e sort} is the closed enumeration of node categories the CBOR data model 9 + defines (RFC 8949), one per major type — with major type 7 split into its 10 + simple-value sub-tags. A {e kind} is the specific human-readable label for 11 + one instance, built from a sort plus an identifier. *) 12 + 13 + type t = 14 + | Unsigned (** Unsigned integer (major type 0). *) 15 + | Negative (** Negative integer (major type 1). *) 16 + | Bytes (** Byte string (major type 2). *) 17 + | Text (** Text string (major type 3). *) 18 + | Array (** Array (major type 4). *) 19 + | Map (** Map (major type 5). *) 20 + | Tag (** Tagged data item (major type 6). *) 21 + | Bool (** Boolean simple values (20/21, major 7). *) 22 + | Null (** Null simple value (22, major 7). *) 23 + | Undefined (** Undefined simple value (23, major 7). *) 24 + | Simple (** Other simple value (major 7). *) 25 + | Float (** Floating-point (major 7 ieee). *) 26 + 27 + val to_string : t -> string 28 + (** [to_string sort] is a human-readable name for [sort]. *) 29 + 30 + val pp : Format.formatter -> t -> unit 31 + (** [pp] formats sorts. *) 32 + 33 + val kinded : kind:string -> t -> string 34 + (** [kinded ~kind s] is [kind ^ " " ^ to_string s] when [kind] is non-empty, 35 + otherwise {!to_string} [s]. *) 36 + 37 + val or_kind : kind:string -> t -> string 38 + (** [or_kind ~kind s] is [kind] when non-empty, otherwise {!to_string} [s]. *)
+13
lib/value.ml
··· 16 16 | Simple of int 17 17 | Float of float 18 18 19 + let sort = function 20 + | Int z -> if Z.sign z >= 0 then Sort.Unsigned else Sort.Negative 21 + | Bytes _ -> Sort.Bytes 22 + | Text _ -> Sort.Text 23 + | Array _ -> Sort.Array 24 + | Map _ -> Sort.Map 25 + | Tag _ -> Sort.Tag 26 + | Bool _ -> Sort.Bool 27 + | Null -> Sort.Null 28 + | Undefined -> Sort.Undefined 29 + | Simple _ -> Sort.Simple 30 + | Float _ -> Sort.Float 31 + 19 32 (* Constructors *) 20 33 let int n = Int (Z.of_int n) 21 34 let int64 n = Int (Z.of_int64 n)
+4
lib/value.mli
··· 65 65 (** Floating-point number. May be encoded as half (16-bit), single 66 66 (32-bit), or double (64-bit) precision IEEE 754. *) 67 67 68 + val sort : t -> Sort.t 69 + (** [sort v] is the CBOR sort of [v]. Inspects [Z.sign] on {!Int} to distinguish 70 + {!Sort.Unsigned} from {!Sort.Negative}. *) 71 + 68 72 (** {1:constructors Constructors} 69 73 70 74 Convenience constructors for common cases. *)