···447447 )
448448449449 let codec_jsont : codec Jsont.t = Jsont.rec' codec_jsont_lazy
450450+451451+ (* Shared helpers for name-dispatched object codecs *)
452452+ let find_name mems =
453453+ List.find_map (fun ((name, _), value) ->
454454+ if name = "name" then match value with
455455+ | Jsont.String (s, _) -> Some s
456456+ | _ -> None
457457+ else None) mems
458458+459459+ let find_config mems =
460460+ List.find_map (fun ((name, _), value) ->
461461+ if name = "configuration" then Some value else None) mems
462462+463463+ let decode_config codec_t config_json =
464464+ match Jsont.Json.decode codec_t config_json with
465465+ | Ok v -> v | Error e -> failwith e
466466+467467+ let encode_named name config_json =
468468+ let mems = [ (("name", Jsont.Meta.none), Jsont.Json.string name) ] in
469469+ let mems = match config_json with
470470+ | None -> mems
471471+ | Some c -> mems @ [ (("configuration", Jsont.Meta.none), c) ]
472472+ in
473473+ Jsont.Json.object' mems
474474+475475+ let encode_config codec_t v =
476476+ match Jsont.Json.encode codec_t v with
477477+ | Ok j -> j | Error e -> failwith e
478478+479479+ let decode_other_ext json =
480480+ match Jsont.Json.decode Other_ext.jsont json with
481481+ | Ok o -> o | Error e -> failwith e
482482+483483+ let encode_other_ext o =
484484+ match Jsont.Json.encode Other_ext.jsont o with
485485+ | Ok j -> j | Error e -> failwith e
486486+487487+ module Data_type = struct
488488+ type t = [
489489+ | `Bool | `Int8 | `Int16 | `Int32 | `Int64
490490+ | `Uint8 | `Uint16 | `Uint32 | `Uint64
491491+ | `Float16 | `Float32 | `Float64
492492+ | `Complex64 | `Complex128
493493+ | `Raw of int
494494+ | `Other of Other_ext.t
495495+ ]
496496+ end
497497+498498+ let data_type_jsont : Data_type.t Jsont.t =
499499+ let string_table = [
500500+ "bool", (`Bool : Data_type.t);
501501+ "int8", `Int8;
502502+ "int16", `Int16;
503503+ "int32", `Int32;
504504+ "int64", `Int64;
505505+ "uint8", `Uint8;
506506+ "uint16", `Uint16;
507507+ "uint32", `Uint32;
508508+ "uint64", `Uint64;
509509+ "float16", `Float16;
510510+ "float32", `Float32;
511511+ "float64", `Float64;
512512+ "complex64", `Complex64;
513513+ "complex128", `Complex128;
514514+ ] in
515515+ let enc_string : Data_type.t -> string = function
516516+ | `Bool -> "bool"
517517+ | `Int8 -> "int8"
518518+ | `Int16 -> "int16"
519519+ | `Int32 -> "int32"
520520+ | `Int64 -> "int64"
521521+ | `Uint8 -> "uint8"
522522+ | `Uint16 -> "uint16"
523523+ | `Uint32 -> "uint32"
524524+ | `Uint64 -> "uint64"
525525+ | `Float16 -> "float16"
526526+ | `Float32 -> "float32"
527527+ | `Float64 -> "float64"
528528+ | `Complex64 -> "complex64"
529529+ | `Complex128 -> "complex128"
530530+ | `Raw n -> Printf.sprintf "r%d" n
531531+ | `Other _ -> assert false
532532+ in
533533+ let dec_string =
534534+ Jsont.map ~kind:"V3.Data_type.string"
535535+ ~dec:(fun s ->
536536+ match List.assoc_opt s string_table with
537537+ | Some v -> v
538538+ | None ->
539539+ (* Check for r<bits> raw type *)
540540+ if String.length s >= 2 && s.[0] = 'r' then
541541+ let bits_str = String.sub s 1 (String.length s - 1) in
542542+ (try `Raw (int_of_string bits_str)
543543+ with _ -> failwith (Printf.sprintf "V3.Data_type: unknown type %s" s))
544544+ else
545545+ failwith (Printf.sprintf "V3.Data_type: unknown type %s" s))
546546+ ~enc:enc_string
547547+ Jsont.string
548548+ in
549549+ let dec_object =
550550+ Jsont.map ~kind:"V3.Data_type.object"
551551+ ~dec:(fun json -> `Other (decode_other_ext json))
552552+ ~enc:(function
553553+ | `Other o -> encode_other_ext o
554554+ | _ -> assert false)
555555+ Jsont.json
556556+ in
557557+ Jsont.any ~kind:"V3.Data_type"
558558+ ~dec_string
559559+ ~dec_object
560560+ ~enc:(function
561561+ | `Other _ -> dec_object
562562+ | v -> ignore v; dec_string)
563563+ ()
564564+565565+ module Chunk_grid = struct
566566+ module Regular = struct
567567+ type t = { chunk_shape : int list }
568568+ let chunk_shape t = t.chunk_shape
569569+ let jsont =
570570+ Jsont.Object.map ~kind:"Regular.config" (fun cs -> { chunk_shape = cs })
571571+ |> Jsont.Object.mem "chunk_shape" (Jsont.list Jsont.int) ~enc:(fun t -> t.chunk_shape)
572572+ |> Jsont.Object.skip_unknown
573573+ |> Jsont.Object.finish
574574+ end
575575+576576+ type t = [ `Regular of Regular.t | `Other of Other_ext.t ]
577577+ end
578578+579579+ let chunk_grid_jsont : Chunk_grid.t Jsont.t =
580580+ Jsont.map ~kind:"V3.Chunk_grid"
581581+ ~dec:(fun json ->
582582+ match json with
583583+ | Jsont.Object (mems, _) ->
584584+ let name = match find_name mems with
585585+ | Some n -> n
586586+ | None -> failwith "chunk_grid: missing name"
587587+ in
588588+ let config = find_config mems in
589589+ (match name with
590590+ | "regular" ->
591591+ `Regular (decode_config Chunk_grid.Regular.jsont (Option.get config))
592592+ | _ -> `Other (decode_other_ext json))
593593+ | _ -> failwith "chunk_grid: expected object")
594594+ ~enc:(function
595595+ | `Regular r ->
596596+ encode_named "regular" (Some (encode_config Chunk_grid.Regular.jsont r))
597597+ | `Other o -> encode_other_ext o)
598598+ Jsont.json
599599+600600+ module Chunk_key_encoding = struct
601601+ module Default = struct
602602+ type t = { separator : [ `Slash | `Dot ] }
603603+ let separator t = t.separator
604604+ let separator_jsont =
605605+ Jsont.enum ~kind:"separator" ["/", `Slash; ".", `Dot]
606606+ let jsont =
607607+ Jsont.Object.map ~kind:"Default.config" (fun sep -> { separator = sep })
608608+ |> Jsont.Object.mem "separator" separator_jsont ~enc:(fun t -> t.separator)
609609+ |> Jsont.Object.skip_unknown
610610+ |> Jsont.Object.finish
611611+ end
612612+613613+ type t = [ `Default of Default.t | `Other of Other_ext.t ]
614614+ end
615615+616616+ let chunk_key_encoding_jsont : Chunk_key_encoding.t Jsont.t =
617617+ Jsont.map ~kind:"V3.Chunk_key_encoding"
618618+ ~dec:(fun json ->
619619+ match json with
620620+ | Jsont.Object (mems, _) ->
621621+ let name = match find_name mems with
622622+ | Some n -> n
623623+ | None -> failwith "chunk_key_encoding: missing name"
624624+ in
625625+ let config = find_config mems in
626626+ (match name with
627627+ | "default" ->
628628+ `Default (decode_config Chunk_key_encoding.Default.jsont (Option.get config))
629629+ | _ -> `Other (decode_other_ext json))
630630+ | _ -> failwith "chunk_key_encoding: expected object")
631631+ ~enc:(function
632632+ | `Default d ->
633633+ encode_named "default" (Some (encode_config Chunk_key_encoding.Default.jsont d))
634634+ | `Other o -> encode_other_ext o)
635635+ Jsont.json
636636+637637+ module Array_meta = struct
638638+ type t = {
639639+ shape : int list;
640640+ data_type : Data_type.t;
641641+ chunk_grid : Chunk_grid.t;
642642+ chunk_key_encoding : Chunk_key_encoding.t;
643643+ codecs : codec list;
644644+ fill_value : fill_value;
645645+ dimension_names : string option list option;
646646+ storage_transformers : Other_ext.t list option;
647647+ unknown : Jsont.json;
648648+ }
649649+650650+ let shape t = t.shape
651651+ let data_type t = t.data_type
652652+ let chunk_grid t = t.chunk_grid
653653+ let chunk_key_encoding t = t.chunk_key_encoding
654654+ let codecs t = t.codecs
655655+ let fill_value t = t.fill_value
656656+ let dimension_names t = t.dimension_names
657657+ let storage_transformers t = t.storage_transformers
658658+ let unknown t = t.unknown
659659+ end
660660+661661+ let array_meta_jsont : Array_meta.t Jsont.t =
662662+ Jsont.Object.map ~kind:"V3.Array_meta"
663663+ (fun _zarr_format _node_type sh dt cg cke cs fv dn st _attrs unk ->
664664+ Array_meta.{
665665+ shape = sh; data_type = dt; chunk_grid = cg; chunk_key_encoding = cke;
666666+ codecs = cs; fill_value = fv; dimension_names = dn; storage_transformers = st;
667667+ unknown = unk;
668668+ })
669669+ |> Jsont.Object.mem "zarr_format" Jsont.int ~enc:(fun _ -> 3)
670670+ |> Jsont.Object.mem "node_type" Jsont.string ~enc:(fun _ -> "array")
671671+ |> Jsont.Object.mem "shape" (Jsont.list Jsont.int)
672672+ ~enc:(fun (t : Array_meta.t) -> t.shape)
673673+ |> Jsont.Object.mem "data_type" data_type_jsont
674674+ ~enc:(fun (t : Array_meta.t) -> t.data_type)
675675+ |> Jsont.Object.mem "chunk_grid" chunk_grid_jsont
676676+ ~enc:(fun (t : Array_meta.t) -> t.chunk_grid)
677677+ |> Jsont.Object.mem "chunk_key_encoding" chunk_key_encoding_jsont
678678+ ~enc:(fun (t : Array_meta.t) -> t.chunk_key_encoding)
679679+ |> Jsont.Object.mem "codecs" (Jsont.list codec_jsont)
680680+ ~enc:(fun (t : Array_meta.t) -> t.codecs)
681681+ |> Jsont.Object.mem "fill_value" fill_value_jsont
682682+ ~enc:(fun (t : Array_meta.t) -> t.fill_value)
683683+ |> Jsont.Object.opt_mem "dimension_names"
684684+ (Jsont.list (Jsont.option Jsont.string))
685685+ ~enc:(fun (t : Array_meta.t) -> t.dimension_names)
686686+ |> Jsont.Object.opt_mem "storage_transformers"
687687+ (Jsont.list Other_ext.jsont)
688688+ ~enc:(fun (t : Array_meta.t) -> t.storage_transformers)
689689+ |> Jsont.Object.opt_mem "attributes" Jsont.json
690690+ ~enc:(fun _ -> None)
691691+ |> Jsont.Object.keep_unknown Jsont.json_mems
692692+ ~enc:(fun (t : Array_meta.t) -> t.unknown)
693693+ |> Jsont.Object.finish
450694end
451695452696module V2 = struct
+66
src/zarr_jsont.mli
···130130 val codec_jsont : codec Jsont.t
131131 (** Codec for {!codec}. Dispatches on the ["name"] field.
132132 Sharding codecs are decoded recursively. *)
133133+134134+ (** V3 data type. Either a core named type (string) or an extension (object). *)
135135+ module Data_type : sig
136136+ type t = [
137137+ | `Bool | `Int8 | `Int16 | `Int32 | `Int64
138138+ | `Uint8 | `Uint16 | `Uint32 | `Uint64
139139+ | `Float16 | `Float32 | `Float64
140140+ | `Complex64 | `Complex128
141141+ | `Raw of int
142142+ | `Other of Other_ext.t
143143+ ]
144144+ end
145145+146146+ val data_type_jsont : Data_type.t Jsont.t
147147+ (** Codec for {!Data_type.t}. Core types decode from JSON strings;
148148+ extension types decode from JSON objects. The [r<bits>] pattern
149149+ decodes as [`Raw bits]. *)
150150+151151+ (** V3 chunk grid specification. *)
152152+ module Chunk_grid : sig
153153+ (** Regular (fixed-shape) chunk grid. *)
154154+ module Regular : sig
155155+ type t
156156+ val chunk_shape : t -> int list
157157+ end
158158+159159+ type t = [ `Regular of Regular.t | `Other of Other_ext.t ]
160160+ end
161161+162162+ val chunk_grid_jsont : Chunk_grid.t Jsont.t
163163+ (** Codec for {!Chunk_grid.t}. Dispatches on the ["name"] field. *)
164164+165165+ (** V3 chunk key encoding specification. *)
166166+ module Chunk_key_encoding : sig
167167+ (** Default chunk key encoding with configurable separator. *)
168168+ module Default : sig
169169+ type t
170170+ val separator : t -> [ `Slash | `Dot ]
171171+ end
172172+173173+ type t = [ `Default of Default.t | `Other of Other_ext.t ]
174174+ end
175175+176176+ val chunk_key_encoding_jsont : Chunk_key_encoding.t Jsont.t
177177+ (** Codec for {!Chunk_key_encoding.t}. Dispatches on the ["name"] field. *)
178178+179179+ (** Complete v3 array metadata. *)
180180+ module Array_meta : sig
181181+ type t
182182+ val shape : t -> int list
183183+ val data_type : t -> Data_type.t
184184+ val chunk_grid : t -> Chunk_grid.t
185185+ val chunk_key_encoding : t -> Chunk_key_encoding.t
186186+ val codecs : t -> codec list
187187+ val fill_value : t -> fill_value
188188+ val dimension_names : t -> string option list option
189189+ val storage_transformers : t -> Other_ext.t list option
190190+ val unknown : t -> Jsont.json
191191+ end
192192+193193+ val array_meta_jsont : Array_meta.t Jsont.t
194194+ (** Codec for {!Array_meta.t}. Decodes and encodes the full v3 array
195195+ metadata object. The ["zarr_format"] and ["node_type"] fields are
196196+ consumed on decode and always written as [3] / ["array"] on encode.
197197+ Dimension names may be absent or contain null entries.
198198+ Unknown fields are preserved. *)
133199end
134200135201(** Zarr v2 compressor and filter codecs. *)
+39
test/test_zarr_jsont.ml
···236236 | _ -> assert false);
237237 print_endline "test_v3_codecs: ok"
238238239239+let test_v3_data_type () =
240240+ let dt = Zarr_jsont.V3.data_type_jsont in
241241+ assert (decode dt {|"float64"|} = `Float64);
242242+ assert (decode dt {|"bool"|} = `Bool);
243243+ assert (decode dt {|"int32"|} = `Int32);
244244+ assert (decode dt {|"r16"|} = `Raw 16);
245245+ let v = decode dt {|{"name":"datetime","configuration":{"unit":"ns"}}|} in
246246+ (match v with
247247+ | `Other o -> assert (Zarr_jsont.Other_ext.name o = "datetime")
248248+ | _ -> assert false);
249249+ print_endline "test_v3_data_type: ok"
250250+251251+let test_v3_array_meta () =
252252+ let json = {|{
253253+ "zarr_format": 3,
254254+ "node_type": "array",
255255+ "shape": [10000, 1000],
256256+ "dimension_names": ["rows", "columns"],
257257+ "data_type": "float64",
258258+ "chunk_grid": {"name": "regular", "configuration": {"chunk_shape": [1000, 100]}},
259259+ "chunk_key_encoding": {"name": "default", "configuration": {"separator": "/"}},
260260+ "codecs": [{"name": "bytes", "configuration": {"endian": "little"}}],
261261+ "fill_value": "NaN",
262262+ "attributes": {"foo": 42}
263263+ }|} in
264264+ let v = decode Zarr_jsont.V3.array_meta_jsont json in
265265+ assert (Zarr_jsont.V3.Array_meta.shape v = [10000; 1000]);
266266+ assert (Zarr_jsont.V3.Array_meta.data_type v = `Float64);
267267+ assert (Zarr_jsont.V3.Array_meta.dimension_names v = Some [Some "rows"; Some "columns"]);
268268+ (match Zarr_jsont.V3.Array_meta.chunk_grid v with
269269+ | `Regular r -> assert (Zarr_jsont.V3.Chunk_grid.Regular.chunk_shape r = [1000; 100])
270270+ | _ -> assert false);
271271+ (match Zarr_jsont.V3.Array_meta.chunk_key_encoding v with
272272+ | `Default d -> assert (Zarr_jsont.V3.Chunk_key_encoding.Default.separator d = `Slash)
273273+ | _ -> assert false);
274274+ print_endline "test_v3_array_meta: ok"
275275+239276let () = test_other_codec ()
240277let () = test_other_ext ()
241278let () = test_fill_value ()
···244281let () = test_v2_filter ()
245282let () = test_v2_array ()
246283let () = test_v3_codecs ()
284284+let () = test_v3_data_type ()
285285+let () = test_v3_array_meta ()