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: V2 Array_meta codec with all fields

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

+106
+41
src/zarr_jsont.ml
··· 412 412 (match Jsont.Json.encode Other_codec.jsont o with 413 413 | Ok j -> j | Error e -> failwith e)) 414 414 Jsont.json 415 + 416 + module Array_meta = struct 417 + type t = { 418 + shape : int list; 419 + chunks : int list; 420 + dtype : dtype; 421 + compressor : compressor option; 422 + fill_value : fill_value; 423 + order : [ `C | `F ]; 424 + filters : filter list option; 425 + dimension_separator : [ `Dot | `Slash ] option; 426 + unknown : Jsont.json; 427 + } 428 + let shape t = t.shape 429 + let chunks t = t.chunks 430 + let dtype t = t.dtype 431 + let compressor t = t.compressor 432 + let fill_value t = t.fill_value 433 + let order t = t.order 434 + let filters t = t.filters 435 + let dimension_separator t = t.dimension_separator 436 + let unknown t = t.unknown 437 + end 438 + 439 + let array_meta_jsont = 440 + let order_jsont = Jsont.enum ~kind:"order" ["C", `C; "F", `F] in 441 + let dim_sep_jsont = Jsont.enum ~kind:"dimension_separator" [".", `Dot; "/", `Slash] in 442 + Jsont.Object.map ~kind:"V2.Array_meta" 443 + (fun _zarr_format s c d comp fv ord filt dim_sep unk -> 444 + Array_meta.{ shape = s; chunks = c; dtype = d; compressor = comp; fill_value = fv; order = ord; filters = filt; dimension_separator = dim_sep; unknown = unk }) 445 + |> Jsont.Object.mem "zarr_format" Jsont.int ~enc:(fun _ -> 2) 446 + |> Jsont.Object.mem "shape" (Jsont.list Jsont.int) ~enc:(fun (t : Array_meta.t) -> t.shape) 447 + |> Jsont.Object.mem "chunks" (Jsont.list Jsont.int) ~enc:(fun (t : Array_meta.t) -> t.chunks) 448 + |> Jsont.Object.mem "dtype" dtype_jsont ~enc:(fun (t : Array_meta.t) -> t.dtype) 449 + |> Jsont.Object.mem "compressor" (Jsont.option compressor_jsont) ~enc:(fun (t : Array_meta.t) -> t.compressor) 450 + |> Jsont.Object.mem "fill_value" fill_value_jsont ~enc:(fun (t : Array_meta.t) -> t.fill_value) 451 + |> Jsont.Object.mem "order" order_jsont ~enc:(fun (t : Array_meta.t) -> t.order) 452 + |> Jsont.Object.mem "filters" (Jsont.option (Jsont.list filter_jsont)) ~enc:(fun (t : Array_meta.t) -> t.filters) 453 + |> Jsont.Object.opt_mem "dimension_separator" dim_sep_jsont ~enc:(fun (t : Array_meta.t) -> t.dimension_separator) 454 + |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun (t : Array_meta.t) -> t.unknown) 455 + |> Jsont.Object.finish 415 456 end
+19
src/zarr_jsont.mli
··· 124 124 125 125 val filter_jsont : filter Jsont.t 126 126 (** Codec for {!filter}. Dispatches on the ["id"] field. *) 127 + 128 + (** Complete v2 [.zarray] array metadata. *) 129 + module Array_meta : sig 130 + type t 131 + val shape : t -> int list 132 + val chunks : t -> int list 133 + val dtype : t -> dtype 134 + val compressor : t -> compressor option 135 + val fill_value : t -> fill_value 136 + val order : t -> [ `C | `F ] 137 + val filters : t -> filter list option 138 + val dimension_separator : t -> [ `Dot | `Slash ] option 139 + val unknown : t -> Jsont.json 140 + end 141 + 142 + val array_meta_jsont : Array_meta.t Jsont.t 143 + (** Codec for {!Array_meta.t}. Decodes and encodes the full [.zarray] 144 + metadata object. The ["zarr_format"] field is consumed on decode and 145 + always written as [2] on encode. Unknown fields are preserved. *) 127 146 end
+46
test/test_zarr_jsont.ml
··· 149 149 | _ -> assert false); 150 150 print_endline "test_v2_filter: ok" 151 151 152 + let test_v2_array () = 153 + let json = {|{ 154 + "zarr_format": 2, 155 + "shape": [10000, 10000], 156 + "chunks": [1000, 1000], 157 + "dtype": "<f8", 158 + "compressor": {"id": "blosc", "cname": "lz4", "clevel": 5, "shuffle": 1}, 159 + "fill_value": "NaN", 160 + "order": "C", 161 + "filters": [{"id": "delta", "dtype": "<f8", "astype": "<f4"}] 162 + }|} in 163 + let v = decode Zarr_jsont.V2.array_meta_jsont json in 164 + assert (Zarr_jsont.V2.Array_meta.shape v = [10000; 10000]); 165 + assert (Zarr_jsont.V2.Array_meta.chunks v = [1000; 1000]); 166 + assert (Zarr_jsont.V2.Array_meta.dtype v = `Float (`Little, 8)); 167 + assert (Zarr_jsont.V2.Array_meta.order v = `C); 168 + (match Zarr_jsont.V2.Array_meta.compressor v with 169 + | Some (`Blosc b) -> 170 + assert (Zarr_jsont.V2.Compressor.Blosc.cname b = "lz4") 171 + | _ -> assert false); 172 + (match Zarr_jsont.V2.Array_meta.filters v with 173 + | Some [(`Delta _)] -> () 174 + | _ -> assert false); 175 + (match Zarr_jsont.V2.Array_meta.fill_value v with 176 + | `Float f -> assert (Float.is_nan f) 177 + | _ -> assert false); 178 + (* roundtrip *) 179 + let json' = encode Zarr_jsont.V2.array_meta_jsont v in 180 + let _ = decode Zarr_jsont.V2.array_meta_jsont json' in 181 + (* null compressor and filters *) 182 + let json2 = {|{ 183 + "zarr_format": 2, 184 + "shape": [20, 20], 185 + "chunks": [10, 10], 186 + "dtype": "<i4", 187 + "compressor": null, 188 + "fill_value": 42, 189 + "order": "C", 190 + "filters": null 191 + }|} in 192 + let v2 = decode Zarr_jsont.V2.array_meta_jsont json2 in 193 + assert (Zarr_jsont.V2.Array_meta.compressor v2 = None); 194 + assert (Zarr_jsont.V2.Array_meta.filters v2 = None); 195 + print_endline "test_v2_array: ok" 196 + 152 197 let () = test_other_codec () 153 198 let () = test_other_ext () 154 199 let () = test_fill_value () 155 200 let () = test_dtype () 156 201 let () = test_v2_compressor () 157 202 let () = test_v2_filter () 203 + let () = test_v2_array ()