package containers
A modular, clean and powerful extension of the OCaml standard library
Install
Dune Dependency
Authors
Maintainers
Sources
containers-3.15.tbz
sha256=92143ceb4785ae5f8a07f3ab4ab9f6f32d31ead0536e9be4fdb818dd3c677e58
sha512=5fa80189d0e177af2302b48e72b70299d51fc36ac2019e1cbf389ff6a7f4705b10089405b5a719b3e4845b0d1349a47a967f865dc2e4e3f0d5a0167ef6c31431
doc/src/containers.cbor/containers_cbor.ml.html
Source file containers_cbor.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
module Fmt = CCFormat type t = [ `Null | `Undefined | `Simple of int | `Bool of bool | `Int of int64 | `Float of float | `Bytes of string | `Text of string | `Array of t list | `Map of (t * t) list | `Tag of int * t ] let rec pp_diagnostic out (self : t) = match self with | `Null -> Fmt.string out "null" | `Undefined -> Fmt.string out "undefined" | `Simple i -> Fmt.fprintf out "simple(%d)" i | `Bool b -> Fmt.bool out b | `Int i -> Fmt.int64 out i | `Float f -> Fmt.float out f | `Bytes b -> Fmt.fprintf out "h'%s'" (CCString.to_hex b) | `Text s -> Fmt.fprintf out "%S" s | `Array l -> Fmt.fprintf out "[@["; List.iteri (fun i x -> if i > 0 then Fmt.fprintf out ",@ "; pp_diagnostic out x) l; Fmt.fprintf out "@]]" | `Map l -> Fmt.fprintf out "{@["; List.iteri (fun i (k, v) -> if i > 0 then Fmt.fprintf out ",@ "; Fmt.fprintf out "@[%a:@ %a@]" pp_diagnostic k pp_diagnostic v) l; Fmt.fprintf out "@]}" | `Tag (i, x) -> Fmt.fprintf out "%d(@[%a@])" i pp_diagnostic x let to_string_diagnostic (self : t) : string = Format.asprintf "@[<h>%a@]" pp_diagnostic self exception Indefinite let[@inline] i64_to_int i = let j = Int64.to_int i in if Int64.(of_int j = i) then j else failwith "int64 does not fit in int" let decode_exn (s : string) : t = let b = Bytes.unsafe_of_string s in let i = ref 0 in (* currently at end delimiter? *) let[@inline] is_break_stop_code () = Char.code s.[!i] = 0b111_11111 in let[@inline] read_i8 () = let c = Char.code s.[!i] in incr i; c in let[@inline] read_i16 () = let c = Bytes.get_uint16_be b !i in i := !i + 2; c in let[@inline] read_i32 () = let c = Bytes.get_int32_be b !i in i := !i + 4; c in let[@inline] read_i64 () = let c = Bytes.get_int64_be b !i in i := !i + 8; c in let reserve_n n = let j = !i in if j + n > String.length s then failwith "cbor: cannot extract slice"; i := !i + n; j in (* read integer value from least significant bits *) let read_int ~allow_indefinite low = match low with | _ when low < 0 -> failwith "cbor: invalid length" | _ when low < 24 -> Int64.of_int low | 24 -> Int64.of_int (read_i8 ()) | 25 -> Int64.of_int (read_i16 ()) | 26 -> Int64.of_int32 (read_i32 ()) | 27 -> read_i64 () | 28 | 29 | 30 -> failwith "cbor: invalid length" | 31 -> if allow_indefinite then raise_notrace Indefinite else failwith "cbor: invalid integer 31 in this context" | _ -> assert false in (* appendix D double decode_half(unsigned char *halfp) { unsigned half = (halfp[0] << 8) + halfp[1]; unsigned exp = (half >> 10) & 0x1f; unsigned mant = half & 0x3ff; double val; if (exp == 0) val = ldexp(mant, -24); else if (exp != 31) val = ldexp(mant + 1024, exp - 25); else val = mant == 0 ? INFINITY : NAN; return half & 0x8000 ? -val : val; } *) let decode_f16 (half : int) : float = (* exponent is bits 15:10 *) let exp = (half lsr 10) land 0x1f in (* mantissa is bits 9:0 *) let mant = half land 0x3ff in let value = if exp = 0 then ldexp (float mant) (-24) else if exp <> 31 then ldexp (float (mant + 1024)) (exp - 25) else if mant = 0 then infinity else nan in if half land 0x8000 <> 0 then -.value else value in (* roughly follow https://www.rfc-editor.org/rfc/rfc8949.html#pseudocode *) let rec read_value () = let c = read_i8 () in let high = (c land 0b111_00000) lsr 5 in let low = c land 0b000_11111 in match high with | 0 -> `Int (read_int ~allow_indefinite:false low) | 1 -> let i = read_int ~allow_indefinite:false low in `Int Int64.(sub minus_one i) | 2 -> let s = read_bytes ~ty:`Bytes low in `Bytes s | 3 -> let s = read_bytes ~ty:`String low in `Text s | 4 -> let l = match read_int ~allow_indefinite:true low |> i64_to_int with | len -> List.init len (fun _ -> read_value ()) | exception Indefinite -> let l = ref [] in while not (is_break_stop_code ()) do l := read_value () :: !l done; incr i; (* consume stop code *) List.rev !l in `Array l | 5 -> let l = match read_int ~allow_indefinite:true low |> i64_to_int with | len -> List.init len (fun _ -> read_pair ()) | exception Indefinite -> let l = ref [] in while not (is_break_stop_code ()) do l := read_pair () :: !l done; incr i; (* consume stop code *) List.rev !l in `Map l | 6 -> let tag = read_int ~allow_indefinite:false low |> i64_to_int in let v = read_value () in `Tag (tag, v) | 7 -> (* simple or float, https://www.rfc-editor.org/rfc/rfc8949.html#fpnocont *) let i = read_int ~allow_indefinite:false low in (match low with | 20 -> `Bool false | 21 -> `Bool true | 22 -> `Null | 23 -> `Undefined | _ when low <= 24 -> `Simple (i64_to_int i) | 25 -> (* float16 *) `Float (decode_f16 (Int64.to_int i)) | 26 -> (* float 32 *) `Float (Int32.float_of_bits (Int64.to_int32 i)) | 27 -> (* float 64 *) `Float (Int64.float_of_bits i) | 28 | 29 | 30 -> failwith "cbor: malformed" | 31 -> failwith "uncaught 'break' stop code" | _ -> assert false (* unreachable *)) | _ -> (* unreachable *) assert false and read_bytes ~ty low = match read_int ~allow_indefinite:true low |> i64_to_int with | exception Indefinite -> let buf = Buffer.create 32 in while not (is_break_stop_code ()) do match read_value (), ty with | `Text s, `String | `Bytes s, `Bytes -> Buffer.add_string buf s | _ -> failwith "cbor: invalid chunk in indefinite length string/byte" done; incr i; (* consume stop code *) Buffer.contents buf | len -> let off = reserve_n len in String.sub s off len and read_pair () = let k = read_value () in let v = read_value () in k, v in read_value () let decode s = try Ok (decode_exn s) with Failure s -> Error s let encode ?(buf = Buffer.create 32) (self : t) : string = Buffer.clear buf; let[@inline] add_byte (high : int) (low : int) = let i = (high lsl 5) lor low in assert (i land 0xff == i); Buffer.add_char buf (Char.unsafe_chr i) in let add_i64 (i : int64) = Buffer.add_int64_be buf i in (* add unsigned integer, including first tag byte *) let add_uint (high : int) (x : int64) = assert (x >= 0L); if x < 24L then add_byte high (i64_to_int x) else if x <= 0xffL then ( add_byte high 24; Buffer.add_char buf (Char.unsafe_chr (i64_to_int x)) ) else if x <= 0xff_ffL then ( add_byte high 25; Buffer.add_uint16_be buf (i64_to_int x) ) else if x <= 0xff_ff_ff_ffL then ( add_byte high 26; Buffer.add_int32_be buf (Int64.to_int32 x) ) else ( add_byte high 27; Buffer.add_int64_be buf x ) in let rec encode_val (self : t) : unit = match self with | `Bool false -> add_byte 7 20 | `Bool true -> add_byte 7 21 | `Null -> add_byte 7 22 | `Undefined -> add_byte 7 23 | `Simple i -> if i < 24 then add_byte 7 i else if i <= 0xff then ( add_byte 7 24; Buffer.add_char buf (Char.unsafe_chr i) ) else failwith "cbor: simple value too high (above 255)" | `Float f -> add_byte 7 27; (* float 64 *) add_i64 (Int64.bits_of_float f) | `Array l -> add_uint 4 (Int64.of_int (List.length l)); List.iter encode_val l | `Map l -> add_uint 5 (Int64.of_int (List.length l)); List.iter (fun (k, v) -> encode_val k; encode_val v) l | `Text s -> add_uint 3 (Int64.of_int (String.length s)); Buffer.add_string buf s | `Bytes s -> add_uint 2 (Int64.of_int (String.length s)); Buffer.add_string buf s | `Tag (t, v) -> add_uint 6 (Int64.of_int t); encode_val v | `Int i -> if i >= Int64.zero then add_uint 0 i else if Int64.(add min_int 2L) > i then ( (* large negative int, be careful. encode [(-i)-1] via int64. *) add_byte 1 27; Buffer.add_int64_be buf Int64.(neg (add 1L i)) ) else add_uint 1 Int64.(sub (neg i) one) in encode_val self; Buffer.contents buf
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>