OCaml Zarr jsont codecs for v2/v3 and common conventions
0
fork

Configure Feed

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

feat: top-level Zarr.t dispatch codec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

+121
+50
src/zarr_jsont.ml
··· 1309 1309 in 1310 1310 Jsont.Json.object' mems) 1311 1311 Jsont.json 1312 + 1313 + type t = [ `V2 of V2_node.t | `V3 of V3_node.t ] 1314 + 1315 + let jsont : t Jsont.t = 1316 + let find_zarr_format mems = 1317 + List.find_map (fun ((n, _), v) -> 1318 + if n = "zarr_format" then 1319 + match v with 1320 + | Jsont.Number (f, _) -> Some (int_of_float f) 1321 + | _ -> None 1322 + else None) mems 1323 + in 1324 + let has_shape mems = 1325 + List.exists (fun ((k, _), _) -> k = "shape") mems 1326 + in 1327 + Jsont.map ~kind:"Zarr" 1328 + ~dec:(fun json -> 1329 + let mems = match json with 1330 + | Jsont.Object (m, _) -> m 1331 + | _ -> failwith "jsont: expected object" 1332 + in 1333 + let zarr_format = match find_zarr_format mems with 1334 + | Some n -> n 1335 + | None -> failwith "jsont: missing zarr_format" 1336 + in 1337 + match zarr_format with 1338 + | 2 -> 1339 + if has_shape mems then 1340 + match Jsont.Json.decode v2_array_jsont json with 1341 + | Ok n -> `V2 n | Error e -> failwith e 1342 + else 1343 + (match Jsont.Json.decode v2_group_jsont json with 1344 + | Ok n -> `V2 n | Error e -> failwith e) 1345 + | 3 -> 1346 + (match Jsont.Json.decode v3_jsont json with 1347 + | Ok n -> `V3 n | Error e -> failwith e) 1348 + | n -> failwith (Printf.sprintf "jsont: unknown zarr_format: %d" n)) 1349 + ~enc:(function 1350 + | `V2 node -> 1351 + (match V2_node.kind node with 1352 + | `Array _ -> 1353 + (match Jsont.Json.encode v2_array_jsont node with 1354 + | Ok j -> j | Error e -> failwith e) 1355 + | `Group -> 1356 + (match Jsont.Json.encode v2_group_jsont node with 1357 + | Ok j -> j | Error e -> failwith e)) 1358 + | `V3 node -> 1359 + (match Jsont.Json.encode v3_jsont node with 1360 + | Ok j -> j | Error e -> failwith e)) 1361 + Jsont.json
+11
src/zarr_jsont.mli
··· 417 417 The ["attributes"] sub-object, if present, is decoded via {!attrs_jsont} and 418 418 stored in the node's [attrs] field. On encode, attributes are re-inserted 419 419 as the ["attributes"] member only when non-empty. *) 420 + 421 + type t = [ `V2 of V2_node.t | `V3 of V3_node.t ] 422 + (** A unified Zarr node: either a v2 node or a v3 node. *) 423 + 424 + val jsont : t Jsont.t 425 + (** Top-level dispatch codec for Zarr metadata. 426 + 427 + Decodes any Zarr metadata JSON object by inspecting the ["zarr_format"] 428 + field and dispatching to {!v2_array_jsont}, {!v2_group_jsont}, or 429 + {!v3_jsont} as appropriate. V2 arrays are distinguished from v2 groups 430 + by the presence of a ["shape"] field. *)
+60
test/test_zarr_jsont.ml
··· 457 457 | None -> assert false); 458 458 print_endline "test_v3_node_array_with_attrs: ok" 459 459 460 + let test_dispatch_v2_array () = 461 + let json = {|{ 462 + "zarr_format": 2, 463 + "shape": [20, 20], 464 + "chunks": [10, 10], 465 + "dtype": "<i4", 466 + "compressor": {"id": "zlib", "level": 1}, 467 + "fill_value": 42, 468 + "order": "C", 469 + "filters": null 470 + }|} in 471 + let v = decode Zarr_jsont.jsont json in 472 + (match v with 473 + | `V2 node -> 474 + (match Zarr_jsont.V2_node.kind node with 475 + | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [20; 20]) 476 + | `Group -> assert false) 477 + | `V3 _ -> assert false); 478 + print_endline "test_dispatch_v2_array: ok" 479 + 480 + let test_dispatch_v2_group () = 481 + let json = {|{"zarr_format": 2}|} in 482 + let v = decode Zarr_jsont.jsont json in 483 + (match v with 484 + | `V2 node -> assert (Zarr_jsont.V2_node.kind node = `Group) 485 + | `V3 _ -> assert false); 486 + print_endline "test_dispatch_v2_group: ok" 487 + 488 + let test_dispatch_v3_array () = 489 + let json = {|{ 490 + "zarr_format": 3, 491 + "node_type": "array", 492 + "shape": [100], 493 + "data_type": "int32", 494 + "chunk_grid": {"name": "regular", "configuration": {"chunk_shape": [10]}}, 495 + "chunk_key_encoding": {"name": "default", "configuration": {"separator": "/"}}, 496 + "codecs": [{"name": "bytes", "configuration": {"endian": "little"}}], 497 + "fill_value": 0 498 + }|} in 499 + let v = decode Zarr_jsont.jsont json in 500 + (match v with 501 + | `V3 node -> 502 + (match Zarr_jsont.V3_node.kind node with 503 + | `Array a -> assert (Zarr_jsont.V3.Array_meta.data_type a = `Int32) 504 + | `Group -> assert false) 505 + | `V2 _ -> assert false); 506 + print_endline "test_dispatch_v3_array: ok" 507 + 508 + let test_dispatch_v3_group () = 509 + let json = {|{"zarr_format": 3, "node_type": "group"}|} in 510 + let v = decode Zarr_jsont.jsont json in 511 + (match v with 512 + | `V3 node -> assert (Zarr_jsont.V3_node.kind node = `Group) 513 + | `V2 _ -> assert false); 514 + print_endline "test_dispatch_v3_group: ok" 515 + 460 516 let () = test_other_codec () 461 517 let () = test_other_ext () 462 518 let () = test_fill_value () ··· 476 532 let () = test_v3_node_group () 477 533 let () = test_v3_node_array () 478 534 let () = test_v3_node_array_with_attrs () 535 + let () = test_dispatch_v2_array () 536 + let () = test_dispatch_v2_group () 537 + let () = test_dispatch_v3_array () 538 + let () = test_dispatch_v3_group ()