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.

fmt

+1798 -1437
+1 -1
.ocamlformat
··· 1 - version = 0.27.0 1 + version = 0.28.1
+34 -30
bin/zarr_inspect.ml
··· 9 9 let read_file path = 10 10 try 11 11 let ic = open_in path in 12 - Fun.protect ~finally:(fun () -> close_in ic) (fun () -> 13 - let n = in_channel_length ic in 14 - let buf = Bytes.create n in 15 - really_input ic buf 0 n; 16 - Ok (Bytes.to_string buf)) 12 + Fun.protect 13 + ~finally:(fun () -> close_in ic) 14 + (fun () -> 15 + let n = in_channel_length ic in 16 + let buf = Bytes.create n in 17 + really_input ic buf 0 n; 18 + Ok (Bytes.to_string buf)) 17 19 with Sys_error msg -> Error msg 18 20 19 21 (* HTTP fetching via curl *) 20 22 21 23 let read_curl url = 22 24 let tmp = Filename.temp_file "zarr_inspect" ".json" in 23 - Fun.protect ~finally:(fun () -> Sys.remove tmp) (fun () -> 24 - let cmd = Printf.sprintf "curl -sf -o '%s' '%s'" tmp url in 25 - match Sys.command cmd with 26 - | 0 -> read_file tmp 27 - | _ -> Error (Printf.sprintf "curl failed for %s" url)) 25 + Fun.protect 26 + ~finally:(fun () -> Sys.remove tmp) 27 + (fun () -> 28 + let cmd = Printf.sprintf "curl -sf -o '%s' '%s'" tmp url in 29 + match Sys.command cmd with 30 + | 0 -> read_file tmp 31 + | _ -> Error (Printf.sprintf "curl failed for %s" url)) 28 32 29 33 (* Dispatch: URL or local path *) 30 34 31 35 let is_url s = 32 36 let s = String.lowercase_ascii s in 33 - String.length s > 7 && 34 - (String.sub s 0 7 = "http://" || String.sub s 0 8 = "https://") 37 + String.length s > 7 38 + && (String.sub s 0 7 = "http://" || String.sub s 0 8 = "https://") 35 39 36 40 let make_reader base_path = 37 - if is_url base_path then 38 - fun relpath -> read_curl (base_path ^ "/" ^ relpath) 39 - else 40 - fun relpath -> 41 - let full = Filename.concat base_path relpath in 42 - read_file full 41 + if is_url base_path then fun relpath -> read_curl (base_path ^ "/" ^ relpath) 42 + else fun relpath -> 43 + let full = Filename.concat base_path relpath in 44 + read_file full 43 45 44 46 (* Pretty-print *) 45 47 ··· 56 58 let read = make_reader path in 57 59 match Zarr_jsont.probe ~read path with 58 60 | Ok result -> 59 - pretty_print_result result; 60 - `Ok () 61 - | Error msg -> 62 - `Error (false, msg) 61 + pretty_print_result result; 62 + `Ok () 63 + | Error msg -> `Error (false, msg) 63 64 64 65 let cmd = 65 66 let doc = "Inspect zarr store metadata" in 66 - let man = [ 67 - `S Manpage.s_description; 68 - `P "Reads zarr v2 or v3 metadata from a local directory or HTTP URL, \ 69 - decodes it using typed codecs, and pretty-prints the re-encoded JSON."; 70 - `S Manpage.s_examples; 71 - `Pre " zarr-inspect ./my-dataset"; 72 - `Pre " zarr-inspect https://example.com/zarr-store"; 73 - ] in 67 + let man = 68 + [ 69 + `S Manpage.s_description; 70 + `P 71 + "Reads zarr v2 or v3 metadata from a local directory or HTTP URL, \ 72 + decodes it using typed codecs, and pretty-prints the re-encoded JSON."; 73 + `S Manpage.s_examples; 74 + `Pre " zarr-inspect ./my-dataset"; 75 + `Pre " zarr-inspect https://example.com/zarr-store"; 76 + ] 77 + in 74 78 let info = Cmd.info "zarr-inspect" ~version:"0.1.0" ~doc ~man in 75 79 Cmd.v info Term.(ret (const run $ path_arg)) 76 80
+1246 -932
src/zarr_jsont.ml
··· 18 18 |> Jsont.Object.finish 19 19 end 20 20 21 - type fill_value = [ 22 - | `Null 21 + type fill_value = 22 + [ `Null 23 23 | `Bool of bool 24 24 | `Int of int64 25 25 | `Float of float 26 26 | `Complex of float * float 27 - | `Bytes of string 28 - ] 27 + | `Bytes of string ] 29 28 30 29 let fill_value_jsont = 31 30 (* Decode a float from a JSON number, deciding if it should be `Int or `Float *) 32 31 let dec_number_to_fill f = 33 - if Float.is_finite f && Float.is_integer f && f >= Int64.(to_float min_int) && f <= Int64.(to_float max_int) 32 + if 33 + Float.is_finite f && Float.is_integer f 34 + && (f >= Int64.(to_float min_int)) 35 + && f <= Int64.(to_float max_int) 34 36 then `Int (Int64.of_float f) 35 37 else `Float f 36 38 in 37 39 let number_codec = 38 - Jsont.map ~kind:"fill_value_number" 39 - ~dec:dec_number_to_fill 40 + Jsont.map ~kind:"fill_value_number" ~dec:dec_number_to_fill 40 41 ~enc:(function 41 - | `Int i -> Int64.to_float i 42 - | `Float f -> f 43 - | _ -> assert false) 42 + | `Int i -> Int64.to_float i | `Float f -> f | _ -> assert false) 44 43 Jsont.number 45 44 in 46 45 let string_codec = 47 46 Jsont.map ~kind:"fill_value_string" 48 - ~dec:(fun s -> match s with 47 + ~dec:(fun s -> 48 + match s with 49 49 | "NaN" -> `Float Float.nan 50 50 | "Infinity" -> `Float Float.infinity 51 51 | "-Infinity" -> `Float Float.neg_infinity 52 - | _ when String.length s > 2 && s.[0] = '0' && (s.[1] = 'x' || s.[1] = 'X') -> 53 - let i = Int64.of_string s in 54 - `Float (Int64.to_float i) 52 + | _ 53 + when String.length s > 2 && s.[0] = '0' && (s.[1] = 'x' || s.[1] = 'X') 54 + -> 55 + let i = Int64.of_string s in 56 + `Float (Int64.to_float i) 55 57 | _ -> `Bytes s) 56 58 ~enc:(function 57 59 | `Float f when Float.is_nan f -> "NaN" ··· 64 66 (* Array codec: either complex (2 floats) or bytes (list of ints 0-255) *) 65 67 let array_codec = 66 68 Jsont.map ~kind:"fill_value_array" 67 - ~dec:(fun fs -> match fs with 68 - | [r; i] -> `Complex (r, i) 69 + ~dec:(fun fs -> 70 + match fs with 71 + | [ r; i ] -> `Complex (r, i) 69 72 | bs -> 70 - let buf = Bytes.create (List.length bs) in 71 - List.iteri (fun idx b -> Bytes.set buf idx (Char.chr (int_of_float b))) bs; 72 - `Bytes (Bytes.to_string buf)) 73 + let buf = Bytes.create (List.length bs) in 74 + List.iteri 75 + (fun idx b -> Bytes.set buf idx (Char.chr (int_of_float b))) 76 + bs; 77 + `Bytes (Bytes.to_string buf)) 73 78 ~enc:(function 74 - | `Complex (r, i) -> [r; i] 79 + | `Complex (r, i) -> [ r; i ] 75 80 | `Bytes s -> 76 - String.to_seq s |> Seq.map (fun c -> float_of_int (Char.code c)) |> List.of_seq 81 + String.to_seq s 82 + |> Seq.map (fun c -> float_of_int (Char.code c)) 83 + |> List.of_seq 77 84 | _ -> assert false) 78 85 (Jsont.list Jsont.number) 79 86 in ··· 83 90 ~enc:(function `Bool b -> b | _ -> assert false) 84 91 Jsont.bool 85 92 in 86 - Jsont.any ~kind:"fill_value" 87 - ~dec_null:(Jsont.null `Null) 88 - ~dec_bool:bool_codec 89 - ~dec_number:number_codec 90 - ~dec_string:string_codec 91 - ~dec_array:array_codec 93 + Jsont.any ~kind:"fill_value" ~dec_null:(Jsont.null `Null) ~dec_bool:bool_codec 94 + ~dec_number:number_codec ~dec_string:string_codec ~dec_array:array_codec 92 95 ~enc:(function 93 96 | `Null -> Jsont.null `Null 94 97 | `Bool _ -> bool_codec ··· 101 104 102 105 type endian = [ `Little | `Big | `Not_applicable ] 103 106 104 - type dtype = [ 105 - | `Bool 107 + type dtype = 108 + [ `Bool 106 109 | `Int of endian * int 107 110 | `Uint of endian * int 108 111 | `Float of endian * int ··· 112 115 | `String of int 113 116 | `Unicode of endian * int 114 117 | `Raw of int 115 - | `Structured of (string * dtype * int list option) list 116 - ] 118 + | `Structured of (string * dtype * int list option) list ] 117 119 118 120 let parse_endian c = 119 121 match c with ··· 123 125 | c -> Error (Printf.sprintf "unknown endian char '%c'" c) 124 126 125 127 let endian_char = function 126 - | `Little -> '<' | `Big -> '>' | `Not_applicable -> '|' 128 + | `Little -> '<' 129 + | `Big -> '>' 130 + | `Not_applicable -> '|' 127 131 128 132 let parse_typestr s : (dtype, string) result = 129 133 if String.length s < 3 then Error (Printf.sprintf "typestr too short: %s" s) 130 134 else 131 135 match parse_endian s.[0] with 132 136 | Error _ as e -> e 133 - | Ok endian -> 134 - let kind = s.[1] in 135 - let rest = String.sub s 2 (String.length s - 2) in 136 - match kind with 137 - | 'b' -> 138 - let n = int_of_string rest in 139 - if n = 1 then Ok `Bool 140 - else Error (Printf.sprintf "invalid bool size %d" n) 141 - | 'i' -> Ok (`Int (endian, int_of_string rest)) 142 - | 'u' -> Ok (`Uint (endian, int_of_string rest)) 143 - | 'f' -> Ok (`Float (endian, int_of_string rest)) 144 - | 'c' -> Ok (`Complex (endian, int_of_string rest)) 145 - | 'M' -> 146 - if String.length rest > 2 && rest.[0] = '8' && rest.[1] = '[' then 147 - let close = String.index rest ']' in 148 - Ok (`Datetime (endian, String.sub rest 2 (close - 2))) 149 - else Error (Printf.sprintf "invalid datetime typestr: %s" s) 150 - | 'm' -> 151 - if String.length rest > 2 && rest.[0] = '8' && rest.[1] = '[' then 152 - let close = String.index rest ']' in 153 - Ok (`Timedelta (endian, String.sub rest 2 (close - 2))) 154 - else Error (Printf.sprintf "invalid timedelta typestr: %s" s) 155 - | 'S' -> Ok (`String (int_of_string rest)) 156 - | 'U' -> Ok (`Unicode (endian, int_of_string rest)) 157 - | 'V' -> Ok (`Raw (int_of_string rest)) 158 - | c -> Error (Printf.sprintf "unknown dtype kind '%c'" c) 137 + | Ok endian -> ( 138 + let kind = s.[1] in 139 + let rest = String.sub s 2 (String.length s - 2) in 140 + match kind with 141 + | 'b' -> 142 + let n = int_of_string rest in 143 + if n = 1 then Ok `Bool 144 + else Error (Printf.sprintf "invalid bool size %d" n) 145 + | 'i' -> Ok (`Int (endian, int_of_string rest)) 146 + | 'u' -> Ok (`Uint (endian, int_of_string rest)) 147 + | 'f' -> Ok (`Float (endian, int_of_string rest)) 148 + | 'c' -> Ok (`Complex (endian, int_of_string rest)) 149 + | 'M' -> 150 + if String.length rest > 2 && rest.[0] = '8' && rest.[1] = '[' then 151 + let close = String.index rest ']' in 152 + Ok (`Datetime (endian, String.sub rest 2 (close - 2))) 153 + else Error (Printf.sprintf "invalid datetime typestr: %s" s) 154 + | 'm' -> 155 + if String.length rest > 2 && rest.[0] = '8' && rest.[1] = '[' then 156 + let close = String.index rest ']' in 157 + Ok (`Timedelta (endian, String.sub rest 2 (close - 2))) 158 + else Error (Printf.sprintf "invalid timedelta typestr: %s" s) 159 + | 'S' -> Ok (`String (int_of_string rest)) 160 + | 'U' -> Ok (`Unicode (endian, int_of_string rest)) 161 + | 'V' -> Ok (`Raw (int_of_string rest)) 162 + | c -> Error (Printf.sprintf "unknown dtype kind '%c'" c)) 159 163 160 164 let encode_typestr (dt : dtype) : string = 161 165 match dt with ··· 173 177 174 178 (* Helpers for using Jsont codecs inside ~dec/~enc functions. 175 179 These raise Jsont.Error on failure, which the framework catches. *) 176 - let jdec codec json = match Jsont.Json.decode codec json with 177 - | Ok v -> v | Error e -> Jsont.Error.msg Jsont.Meta.none e 180 + let jdec codec json = 181 + match Jsont.Json.decode codec json with 182 + | Ok v -> v 183 + | Error e -> Jsont.Error.msg Jsont.Meta.none e 178 184 179 - let jenc codec v = match Jsont.Json.encode codec v with 180 - | Ok j -> j | Error e -> Jsont.Error.msg Jsont.Meta.none e 185 + let jenc codec v = 186 + match Jsont.Json.encode codec v with 187 + | Ok j -> j 188 + | Error e -> Jsont.Error.msg Jsont.Meta.none e 181 189 182 - let rec dtype_jsont_lazy : dtype Jsont.t Lazy.t = lazy ( 183 - let self = Jsont.rec' dtype_jsont_lazy in 184 - let simple_codec = 185 - Jsont.of_of_string ~kind:"dtype" parse_typestr ~enc:encode_typestr 186 - in 187 - (* A structured field is a JSON array: ["name", dtype] or ["name", dtype, [shape]] *) 188 - let field_jsont = 189 - Jsont.map ~kind:"dtype_field" 190 - ~dec:(fun items -> 191 - let n = List.length items in 192 - if n < 2 then 193 - Jsont.Error.msgf Jsont.Meta.none "dtype field: need at least 2 elements"; 194 - let name = jdec Jsont.string (List.nth items 0) in 195 - let dt = jdec self (List.nth items 1) in 196 - let shape = 197 - if n >= 3 then Some (jdec (Jsont.list Jsont.int) (List.nth items 2)) 198 - else None 199 - in 200 - (name, dt, shape)) 201 - ~enc:(fun (name, dt, shape) -> 202 - let elts = [ Jsont.Json.string name; jenc self dt ] in 203 - match shape with 204 - | None -> elts 205 - | Some s -> elts @ [ jenc (Jsont.list Jsont.int) s ]) 206 - (Jsont.list Jsont.json) 207 - in 208 - let structured_codec = 209 - Jsont.map ~kind:"dtype" 210 - ~dec:(fun fields -> `Structured fields) 211 - ~enc:(function `Structured fields -> fields | _ -> assert false) 212 - (Jsont.list field_jsont) 213 - in 214 - Jsont.any ~kind:"dtype" 215 - ~dec_string:simple_codec 216 - ~dec_array:structured_codec 217 - ~enc:(function 218 - | `Structured _ -> structured_codec 219 - | _ -> simple_codec) 220 - () 221 - ) 190 + let rec dtype_jsont_lazy : dtype Jsont.t Lazy.t = 191 + lazy 192 + (let self = Jsont.rec' dtype_jsont_lazy in 193 + let simple_codec = 194 + Jsont.of_of_string ~kind:"dtype" parse_typestr ~enc:encode_typestr 195 + in 196 + (* A structured field is a JSON array: ["name", dtype] or ["name", dtype, [shape]] *) 197 + let field_jsont = 198 + Jsont.map ~kind:"dtype_field" 199 + ~dec:(fun items -> 200 + let n = List.length items in 201 + if n < 2 then 202 + Jsont.Error.msgf Jsont.Meta.none 203 + "dtype field: need at least 2 elements"; 204 + let name = jdec Jsont.string (List.nth items 0) in 205 + let dt = jdec self (List.nth items 1) in 206 + let shape = 207 + if n >= 3 then 208 + Some (jdec (Jsont.list Jsont.int) (List.nth items 2)) 209 + else None 210 + in 211 + (name, dt, shape)) 212 + ~enc:(fun (name, dt, shape) -> 213 + let elts = [ Jsont.Json.string name; jenc self dt ] in 214 + match shape with 215 + | None -> elts 216 + | Some s -> elts @ [ jenc (Jsont.list Jsont.int) s ]) 217 + (Jsont.list Jsont.json) 218 + in 219 + let structured_codec = 220 + Jsont.map ~kind:"dtype" 221 + ~dec:(fun fields -> `Structured fields) 222 + ~enc:(function `Structured fields -> fields | _ -> assert false) 223 + (Jsont.list field_jsont) 224 + in 225 + Jsont.any ~kind:"dtype" ~dec_string:simple_codec 226 + ~dec_array:structured_codec 227 + ~enc:(function `Structured _ -> structured_codec | _ -> simple_codec) 228 + ()) 222 229 223 230 let dtype_jsont : dtype Jsont.t = Jsont.rec' dtype_jsont_lazy 224 231 225 232 module Other_ext = struct 226 - type t = { name : string; configuration : Jsont.json option; must_understand : bool } 233 + type t = { 234 + name : string; 235 + configuration : Jsont.json option; 236 + must_understand : bool; 237 + } 227 238 228 239 let name e = e.name 229 240 let configuration e = e.configuration 230 241 let must_understand e = e.must_understand 231 - let make name configuration must_understand = { name; configuration; must_understand } 242 + 243 + let make name configuration must_understand = 244 + { name; configuration; must_understand } 232 245 233 246 let jsont = 234 247 Jsont.Object.map ~kind:"Other_ext" make 235 248 |> Jsont.Object.mem "name" Jsont.string ~enc:name 236 249 |> Jsont.Object.opt_mem "configuration" Jsont.json ~enc:configuration 237 - |> Jsont.Object.mem "must_understand" Jsont.bool 238 - ~dec_absent:true 250 + |> Jsont.Object.mem "must_understand" Jsont.bool ~dec_absent:true 239 251 ~enc_omit:(fun v -> v) 240 252 ~enc:must_understand 241 - |> Jsont.Object.skip_unknown 242 - |> Jsont.Object.finish 253 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 243 254 end 244 255 245 256 module V3 = struct 246 257 module Codec = struct 247 258 module Bytes = struct 248 259 type t = { endian : [ `Little | `Big ] option } 260 + 249 261 let endian t = t.endian 250 - let endian_jsont = Jsont.enum ~kind:"endian" ["little", `Little; "big", `Big] 262 + 263 + let endian_jsont = 264 + Jsont.enum ~kind:"endian" [ ("little", `Little); ("big", `Big) ] 265 + 251 266 let jsont = 252 267 Jsont.Object.map ~kind:"Bytes.config" (fun e -> { endian = e }) 253 268 |> Jsont.Object.opt_mem "endian" endian_jsont ~enc:(fun t -> t.endian) 254 - |> Jsont.Object.skip_unknown 255 - |> Jsont.Object.finish 269 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 256 270 end 257 271 258 272 module Gzip = struct 259 273 type t = { level : int } 274 + 260 275 let level t = t.level 276 + 261 277 let jsont = 262 278 Jsont.Object.map ~kind:"Gzip.config" (fun l -> { level = l }) 263 279 |> Jsont.Object.mem "level" Jsont.int ~enc:(fun t -> t.level) 264 - |> Jsont.Object.skip_unknown 265 - |> Jsont.Object.finish 280 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 266 281 end 267 282 268 283 module Blosc = struct ··· 273 288 typesize : int option; 274 289 blocksize : int; 275 290 } 291 + 276 292 let cname t = t.cname 277 293 let clevel t = t.clevel 278 294 let shuffle t = t.shuffle 279 295 let typesize t = t.typesize 280 296 let blocksize t = t.blocksize 281 - let shuffle_jsont = Jsont.enum ~kind:"blosc_shuffle" 282 - ["noshuffle", `Noshuffle; "shuffle", `Shuffle; "bitshuffle", `Bitshuffle] 297 + 298 + let shuffle_jsont = 299 + Jsont.enum ~kind:"blosc_shuffle" 300 + [ 301 + ("noshuffle", `Noshuffle); 302 + ("shuffle", `Shuffle); 303 + ("bitshuffle", `Bitshuffle); 304 + ] 305 + 283 306 let jsont = 284 - Jsont.Object.map ~kind:"Blosc.config" 285 - (fun cn cl sh ts bs -> { cname = cn; clevel = cl; shuffle = sh; typesize = ts; blocksize = bs }) 307 + Jsont.Object.map ~kind:"Blosc.config" (fun cn cl sh ts bs -> 308 + { 309 + cname = cn; 310 + clevel = cl; 311 + shuffle = sh; 312 + typesize = ts; 313 + blocksize = bs; 314 + }) 286 315 |> Jsont.Object.mem "cname" Jsont.string ~enc:(fun t -> t.cname) 287 316 |> Jsont.Object.mem "clevel" Jsont.int ~enc:(fun t -> t.clevel) 288 317 |> Jsont.Object.mem "shuffle" shuffle_jsont ~enc:(fun t -> t.shuffle) 289 318 |> Jsont.Object.opt_mem "typesize" Jsont.int ~enc:(fun t -> t.typesize) 290 319 |> Jsont.Object.mem "blocksize" Jsont.int ~enc:(fun t -> t.blocksize) 291 - |> Jsont.Object.skip_unknown 292 - |> Jsont.Object.finish 320 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 293 321 end 294 322 295 323 module Transpose = struct 296 324 type t = { order : int list } 325 + 297 326 let order t = t.order 327 + 298 328 let jsont = 299 329 Jsont.Object.map ~kind:"Transpose.config" (fun o -> { order = o }) 300 - |> Jsont.Object.mem "order" (Jsont.list Jsont.int) ~enc:(fun t -> t.order) 301 - |> Jsont.Object.skip_unknown 302 - |> Jsont.Object.finish 330 + |> Jsont.Object.mem "order" (Jsont.list Jsont.int) ~enc:(fun t -> 331 + t.order) 332 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 303 333 end 304 334 305 335 module Sharding = struct ··· 309 339 index_codecs : codec list; 310 340 index_location : [ `Start | `End ]; 311 341 } 312 - and codec = [ 313 - | `Bytes of Bytes.t 342 + 343 + and codec = 344 + [ `Bytes of Bytes.t 314 345 | `Gzip of Gzip.t 315 346 | `Blosc of Blosc.t 316 347 | `Crc32c 317 348 | `Transpose of Transpose.t 318 349 | `Sharding of t 319 - | `Other of Other_ext.t 320 - ] 350 + | `Other of Other_ext.t ] 351 + 321 352 let chunk_shape t = t.chunk_shape 322 353 let codecs t = t.codecs 323 354 let index_codecs t = t.index_codecs ··· 329 360 330 361 (* Shared helpers for name-dispatched object codecs *) 331 362 let find_name mems = 332 - List.find_map (fun ((name, _), value) -> 333 - if name = "name" then match value with 334 - | Jsont.String (s, _) -> Some s 335 - | _ -> None 336 - else None) mems 363 + List.find_map 364 + (fun ((name, _), value) -> 365 + if name = "name" then 366 + match value with Jsont.String (s, _) -> Some s | _ -> None 367 + else None) 368 + mems 337 369 338 370 let find_config mems = 339 - List.find_map (fun ((name, _), value) -> 340 - if name = "configuration" then Some value else None) mems 371 + List.find_map 372 + (fun ((name, _), value) -> 373 + if name = "configuration" then Some value else None) 374 + mems 341 375 342 376 let decode_config codec_t config_json = jdec codec_t config_json 343 377 344 378 let encode_named name config_json = 345 379 let mems = [ (("name", Jsont.Meta.none), Jsont.Json.string name) ] in 346 - let mems = match config_json with 380 + let mems = 381 + match config_json with 347 382 | None -> mems 348 383 | Some c -> mems @ [ (("configuration", Jsont.Meta.none), c) ] 349 384 in 350 385 Jsont.Json.object' mems 351 386 352 387 let encode_config codec_t v = jenc codec_t v 353 - 354 388 let decode_other_ext json = jdec Other_ext.jsont json 355 - 356 389 let encode_other_ext o = jenc Other_ext.jsont o 357 390 358 391 let name_dispatch ~kind cases json = 359 392 match json with 360 - | Jsont.Object (mems, _) -> 361 - let name = match find_name mems with 362 - | Some n -> n | None -> Jsont.Error.msgf Jsont.Meta.none "%s: missing name" kind 363 - in 364 - let config = match find_config mems with 365 - | Some c -> c | None -> Jsont.Json.object' [] 366 - in 367 - (match List.assoc_opt name cases with 368 - | Some codec -> jdec codec config 369 - | None -> `Other (jdec Other_ext.jsont json)) 393 + | Jsont.Object (mems, _) -> ( 394 + let name = 395 + match find_name mems with 396 + | Some n -> n 397 + | None -> Jsont.Error.msgf Jsont.Meta.none "%s: missing name" kind 398 + in 399 + let config = 400 + match find_config mems with 401 + | Some c -> c 402 + | None -> Jsont.Json.object' [] 403 + in 404 + match List.assoc_opt name cases with 405 + | Some codec -> jdec codec config 406 + | None -> `Other (jdec Other_ext.jsont json)) 370 407 | _ -> Jsont.Error.msgf Jsont.Meta.none "%s: expected object" kind 371 408 372 - let rec codec_jsont_lazy : codec Jsont.t Lazy.t = lazy ( 373 - let index_location_jsont = 374 - Jsont.enum ~kind:"index_location" ["start", `Start; "end", `End] 375 - in 376 - let sharding_config_jsont = 377 - let codec_list = Jsont.list (Jsont.rec' codec_jsont_lazy) in 378 - Jsont.Object.map ~kind:"Sharding.config" 379 - (fun cs cc ic il -> 380 - Codec.Sharding.{ chunk_shape = cs; codecs = cc; index_codecs = ic; index_location = il }) 381 - |> Jsont.Object.mem "chunk_shape" (Jsont.list Jsont.int) 382 - ~enc:(fun (t : Codec.Sharding.t) -> t.chunk_shape) 383 - |> Jsont.Object.mem "codecs" codec_list 384 - ~enc:(fun (t : Codec.Sharding.t) -> t.codecs) 385 - |> Jsont.Object.mem "index_codecs" codec_list 386 - ~dec_absent:[] 387 - ~enc:(fun (t : Codec.Sharding.t) -> t.index_codecs) 388 - ~enc_omit:(fun l -> l = []) 389 - |> Jsont.Object.mem "index_location" index_location_jsont 390 - ~dec_absent:`End 391 - ~enc:(fun (t : Codec.Sharding.t) -> t.index_location) 392 - ~enc_omit:(fun v -> v = `End) 393 - |> Jsont.Object.skip_unknown 394 - |> Jsont.Object.finish 395 - in 396 - Jsont.map ~kind:"V3.Codec" 397 - ~dec:(fun json -> 398 - match json with 399 - | Jsont.Object (mems, _) -> 400 - let name = match find_name mems with 401 - | Some n -> n 402 - | None -> Jsont.Error.msgf Jsont.Meta.none "codec: missing name" 403 - in 404 - let config = find_config mems in 405 - let config_or_empty = match config with 406 - | Some c -> c | None -> Jsont.Json.object' [] 407 - in 408 - (match name with 409 - | "bytes" -> 410 - `Bytes (decode_config Codec.Bytes.jsont config_or_empty) 411 - | "gzip" -> 412 - `Gzip (decode_config Codec.Gzip.jsont config_or_empty) 413 - | "blosc" -> 414 - `Blosc (decode_config Codec.Blosc.jsont config_or_empty) 415 - | "crc32c" -> `Crc32c 416 - | "transpose" -> 417 - `Transpose (decode_config Codec.Transpose.jsont config_or_empty) 418 - | "sharding_indexed" -> 419 - `Sharding (decode_config sharding_config_jsont config_or_empty) 420 - | _ -> `Other (decode_other_ext json)) 421 - | _ -> Jsont.Error.msgf Jsont.Meta.none "codec: expected object") 422 - ~enc:(function 423 - | `Bytes b -> 424 - encode_named "bytes" (Some (encode_config Codec.Bytes.jsont b)) 425 - | `Gzip g -> 426 - encode_named "gzip" (Some (encode_config Codec.Gzip.jsont g)) 427 - | `Blosc b -> 428 - encode_named "blosc" (Some (encode_config Codec.Blosc.jsont b)) 429 - | `Crc32c -> 430 - encode_named "crc32c" None 431 - | `Transpose t -> 432 - encode_named "transpose" (Some (encode_config Codec.Transpose.jsont t)) 433 - | `Sharding s -> 434 - encode_named "sharding_indexed" (Some (encode_config sharding_config_jsont s)) 435 - | `Other o -> encode_other_ext o) 436 - Jsont.json 437 - ) 409 + let rec codec_jsont_lazy : codec Jsont.t Lazy.t = 410 + lazy 411 + (let index_location_jsont = 412 + Jsont.enum ~kind:"index_location" [ ("start", `Start); ("end", `End) ] 413 + in 414 + let sharding_config_jsont = 415 + let codec_list = Jsont.list (Jsont.rec' codec_jsont_lazy) in 416 + Jsont.Object.map ~kind:"Sharding.config" (fun cs cc ic il -> 417 + Codec.Sharding. 418 + { 419 + chunk_shape = cs; 420 + codecs = cc; 421 + index_codecs = ic; 422 + index_location = il; 423 + }) 424 + |> Jsont.Object.mem "chunk_shape" (Jsont.list Jsont.int) 425 + ~enc:(fun (t : Codec.Sharding.t) -> t.chunk_shape) 426 + |> Jsont.Object.mem "codecs" codec_list 427 + ~enc:(fun (t : Codec.Sharding.t) -> t.codecs) 428 + |> Jsont.Object.mem "index_codecs" codec_list ~dec_absent:[] 429 + ~enc:(fun (t : Codec.Sharding.t) -> t.index_codecs) 430 + ~enc_omit:(fun l -> l = []) 431 + |> Jsont.Object.mem "index_location" index_location_jsont 432 + ~dec_absent:`End 433 + ~enc:(fun (t : Codec.Sharding.t) -> t.index_location) 434 + ~enc_omit:(fun v -> v = `End) 435 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 436 + in 437 + Jsont.map ~kind:"V3.Codec" 438 + ~dec:(fun json -> 439 + match json with 440 + | Jsont.Object (mems, _) -> ( 441 + let name = 442 + match find_name mems with 443 + | Some n -> n 444 + | None -> 445 + Jsont.Error.msgf Jsont.Meta.none "codec: missing name" 446 + in 447 + let config = find_config mems in 448 + let config_or_empty = 449 + match config with Some c -> c | None -> Jsont.Json.object' [] 450 + in 451 + match name with 452 + | "bytes" -> 453 + `Bytes (decode_config Codec.Bytes.jsont config_or_empty) 454 + | "gzip" -> 455 + `Gzip (decode_config Codec.Gzip.jsont config_or_empty) 456 + | "blosc" -> 457 + `Blosc (decode_config Codec.Blosc.jsont config_or_empty) 458 + | "crc32c" -> `Crc32c 459 + | "transpose" -> 460 + `Transpose 461 + (decode_config Codec.Transpose.jsont config_or_empty) 462 + | "sharding_indexed" -> 463 + `Sharding 464 + (decode_config sharding_config_jsont config_or_empty) 465 + | _ -> `Other (decode_other_ext json)) 466 + | _ -> Jsont.Error.msgf Jsont.Meta.none "codec: expected object") 467 + ~enc:(function 468 + | `Bytes b -> 469 + encode_named "bytes" (Some (encode_config Codec.Bytes.jsont b)) 470 + | `Gzip g -> 471 + encode_named "gzip" (Some (encode_config Codec.Gzip.jsont g)) 472 + | `Blosc b -> 473 + encode_named "blosc" (Some (encode_config Codec.Blosc.jsont b)) 474 + | `Crc32c -> encode_named "crc32c" None 475 + | `Transpose t -> 476 + encode_named "transpose" 477 + (Some (encode_config Codec.Transpose.jsont t)) 478 + | `Sharding s -> 479 + encode_named "sharding_indexed" 480 + (Some (encode_config sharding_config_jsont s)) 481 + | `Other o -> encode_other_ext o) 482 + Jsont.json) 438 483 439 484 let codec_jsont : codec Jsont.t = Jsont.rec' codec_jsont_lazy 440 485 441 486 module Data_type = struct 442 - type t = [ 443 - | `Bool | `Int8 | `Int16 | `Int32 | `Int64 444 - | `Uint8 | `Uint16 | `Uint32 | `Uint64 445 - | `Float16 | `Float32 | `Float64 446 - | `Complex64 | `Complex128 487 + type t = 488 + [ `Bool 489 + | `Int8 490 + | `Int16 491 + | `Int32 492 + | `Int64 493 + | `Uint8 494 + | `Uint16 495 + | `Uint32 496 + | `Uint64 497 + | `Float16 498 + | `Float32 499 + | `Float64 500 + | `Complex64 501 + | `Complex128 447 502 | `Raw of int 448 - | `Other of Other_ext.t 449 - ] 503 + | `Other of Other_ext.t ] 450 504 end 451 505 452 506 let data_type_jsont : Data_type.t Jsont.t = 453 - let string_table = [ 454 - "bool", (`Bool : Data_type.t); 455 - "int8", `Int8; 456 - "int16", `Int16; 457 - "int32", `Int32; 458 - "int64", `Int64; 459 - "uint8", `Uint8; 460 - "uint16", `Uint16; 461 - "uint32", `Uint32; 462 - "uint64", `Uint64; 463 - "float16", `Float16; 464 - "float32", `Float32; 465 - "float64", `Float64; 466 - "complex64", `Complex64; 467 - "complex128", `Complex128; 468 - ] in 507 + let string_table = 508 + [ 509 + ("bool", (`Bool : Data_type.t)); 510 + ("int8", `Int8); 511 + ("int16", `Int16); 512 + ("int32", `Int32); 513 + ("int64", `Int64); 514 + ("uint8", `Uint8); 515 + ("uint16", `Uint16); 516 + ("uint32", `Uint32); 517 + ("uint64", `Uint64); 518 + ("float16", `Float16); 519 + ("float32", `Float32); 520 + ("float64", `Float64); 521 + ("complex64", `Complex64); 522 + ("complex128", `Complex128); 523 + ] 524 + in 469 525 let enc_string : Data_type.t -> string = function 470 - | `Bool -> "bool" 471 - | `Int8 -> "int8" 472 - | `Int16 -> "int16" 473 - | `Int32 -> "int32" 474 - | `Int64 -> "int64" 475 - | `Uint8 -> "uint8" 476 - | `Uint16 -> "uint16" 477 - | `Uint32 -> "uint32" 478 - | `Uint64 -> "uint64" 479 - | `Float16 -> "float16" 480 - | `Float32 -> "float32" 481 - | `Float64 -> "float64" 482 - | `Complex64 -> "complex64" 526 + | `Bool -> "bool" 527 + | `Int8 -> "int8" 528 + | `Int16 -> "int16" 529 + | `Int32 -> "int32" 530 + | `Int64 -> "int64" 531 + | `Uint8 -> "uint8" 532 + | `Uint16 -> "uint16" 533 + | `Uint32 -> "uint32" 534 + | `Uint64 -> "uint64" 535 + | `Float16 -> "float16" 536 + | `Float32 -> "float32" 537 + | `Float64 -> "float64" 538 + | `Complex64 -> "complex64" 483 539 | `Complex128 -> "complex128" 484 - | `Raw n -> Printf.sprintf "r%d" n 485 - | `Other _ -> assert false 540 + | `Raw n -> Printf.sprintf "r%d" n 541 + | `Other _ -> assert false 486 542 in 487 543 let dec_string = 488 544 Jsont.map ~kind:"V3.Data_type.string" ··· 490 546 match List.assoc_opt s string_table with 491 547 | Some v -> v 492 548 | None -> 493 - (* Check for r<bits> raw type *) 494 - if String.length s >= 2 && s.[0] = 'r' then 495 - let bits_str = String.sub s 1 (String.length s - 1) in 496 - (try `Raw (int_of_string bits_str) 497 - with _ -> Jsont.Error.msgf Jsont.Meta.none "V3.Data_type: unknown type %s" s) 498 - else 499 - Jsont.Error.msgf Jsont.Meta.none "V3.Data_type: unknown type %s" s) 500 - ~enc:enc_string 501 - Jsont.string 549 + (* Check for r<bits> raw type *) 550 + if String.length s >= 2 && s.[0] = 'r' then 551 + let bits_str = String.sub s 1 (String.length s - 1) in 552 + try `Raw (int_of_string bits_str) 553 + with _ -> 554 + Jsont.Error.msgf Jsont.Meta.none 555 + "V3.Data_type: unknown type %s" s 556 + else 557 + Jsont.Error.msgf Jsont.Meta.none "V3.Data_type: unknown type %s" 558 + s) 559 + ~enc:enc_string Jsont.string 502 560 in 503 561 let dec_object = 504 562 Jsont.map ~kind:"V3.Data_type.object" 505 563 ~dec:(fun json -> `Other (decode_other_ext json)) 506 - ~enc:(function 507 - | `Other o -> encode_other_ext o 508 - | _ -> assert false) 564 + ~enc:(function `Other o -> encode_other_ext o | _ -> assert false) 509 565 Jsont.json 510 566 in 511 - Jsont.any ~kind:"V3.Data_type" 512 - ~dec_string 513 - ~dec_object 514 - ~enc:(function 515 - | `Other _ -> dec_object 516 - | _ -> dec_string) 567 + Jsont.any ~kind:"V3.Data_type" ~dec_string ~dec_object 568 + ~enc:(function `Other _ -> dec_object | _ -> dec_string) 517 569 () 518 570 519 571 module Chunk_grid = struct 520 572 module Regular = struct 521 573 type t = { chunk_shape : int list } 574 + 522 575 let chunk_shape t = t.chunk_shape 576 + 523 577 let jsont = 524 578 Jsont.Object.map ~kind:"Regular.config" (fun cs -> { chunk_shape = cs }) 525 - |> Jsont.Object.mem "chunk_shape" (Jsont.list Jsont.int) ~enc:(fun t -> t.chunk_shape) 526 - |> Jsont.Object.skip_unknown 527 - |> Jsont.Object.finish 579 + |> Jsont.Object.mem "chunk_shape" (Jsont.list Jsont.int) ~enc:(fun t -> 580 + t.chunk_shape) 581 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 528 582 end 529 583 530 584 type t = [ `Regular of Regular.t | `Other of Other_ext.t ] 531 585 end 532 586 533 587 let chunk_grid_jsont : Chunk_grid.t Jsont.t = 534 - let regular_codec = Jsont.map ~kind:"regular_grid" 535 - ~dec:(fun r -> `Regular r) 536 - ~enc:(function `Regular r -> r | _ -> assert false) 537 - Chunk_grid.Regular.jsont 588 + let regular_codec = 589 + Jsont.map ~kind:"regular_grid" 590 + ~dec:(fun r -> `Regular r) 591 + ~enc:(function `Regular r -> r | _ -> assert false) 592 + Chunk_grid.Regular.jsont 538 593 in 539 594 Jsont.map ~kind:"V3.Chunk_grid" 540 - ~dec:(fun json -> name_dispatch ~kind:"chunk_grid" ["regular", regular_codec] json) 595 + ~dec:(fun json -> 596 + name_dispatch ~kind:"chunk_grid" [ ("regular", regular_codec) ] json) 541 597 ~enc:(function 542 598 | `Regular r -> 543 - encode_named "regular" (Some (encode_config Chunk_grid.Regular.jsont r)) 599 + encode_named "regular" 600 + (Some (encode_config Chunk_grid.Regular.jsont r)) 544 601 | `Other o -> encode_other_ext o) 545 602 Jsont.json 546 603 547 604 module Chunk_key_encoding = struct 548 605 module Default = struct 549 606 type t = { separator : [ `Slash | `Dot ] } 607 + 550 608 let separator t = t.separator 609 + 551 610 let separator_jsont = 552 - Jsont.enum ~kind:"separator" ["/", `Slash; ".", `Dot] 611 + Jsont.enum ~kind:"separator" [ ("/", `Slash); (".", `Dot) ] 612 + 553 613 let jsont = 554 614 Jsont.Object.map ~kind:"Default.config" (fun sep -> { separator = sep }) 555 - |> Jsont.Object.mem "separator" separator_jsont ~enc:(fun t -> t.separator) 556 - |> Jsont.Object.skip_unknown 557 - |> Jsont.Object.finish 615 + |> Jsont.Object.mem "separator" separator_jsont ~enc:(fun t -> 616 + t.separator) 617 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 558 618 end 559 619 560 620 type t = [ `Default of Default.t | `Other of Other_ext.t ] 561 621 end 562 622 563 623 let chunk_key_encoding_jsont : Chunk_key_encoding.t Jsont.t = 564 - let default_codec = Jsont.map ~kind:"default_encoding" 565 - ~dec:(fun d -> `Default d) 566 - ~enc:(function `Default d -> d | _ -> assert false) 567 - Chunk_key_encoding.Default.jsont 624 + let default_codec = 625 + Jsont.map ~kind:"default_encoding" 626 + ~dec:(fun d -> `Default d) 627 + ~enc:(function `Default d -> d | _ -> assert false) 628 + Chunk_key_encoding.Default.jsont 568 629 in 569 630 Jsont.map ~kind:"V3.Chunk_key_encoding" 570 - ~dec:(fun json -> name_dispatch ~kind:"chunk_key_encoding" ["default", default_codec] json) 631 + ~dec:(fun json -> 632 + name_dispatch ~kind:"chunk_key_encoding" 633 + [ ("default", default_codec) ] 634 + json) 571 635 ~enc:(function 572 636 | `Default d -> 573 - encode_named "default" (Some (encode_config Chunk_key_encoding.Default.jsont d)) 637 + encode_named "default" 638 + (Some (encode_config Chunk_key_encoding.Default.jsont d)) 574 639 | `Other o -> encode_other_ext o) 575 640 Jsont.json 576 641 ··· 601 666 let array_meta_jsont : Array_meta.t Jsont.t = 602 667 Jsont.Object.map ~kind:"V3.Array_meta" 603 668 (fun _zarr_format _node_type sh dt cg cke cs fv dn st _attrs unk -> 604 - Array_meta.{ 605 - shape = sh; data_type = dt; chunk_grid = cg; chunk_key_encoding = cke; 606 - codecs = cs; fill_value = fv; dimension_names = dn; storage_transformers = st; 607 - unknown = unk; 608 - }) 669 + Array_meta. 670 + { 671 + shape = sh; 672 + data_type = dt; 673 + chunk_grid = cg; 674 + chunk_key_encoding = cke; 675 + codecs = cs; 676 + fill_value = fv; 677 + dimension_names = dn; 678 + storage_transformers = st; 679 + unknown = unk; 680 + }) 609 681 |> Jsont.Object.mem "zarr_format" Jsont.int ~enc:(fun _ -> 3) 610 682 |> Jsont.Object.mem "node_type" Jsont.string ~enc:(fun _ -> "array") 611 683 |> Jsont.Object.mem "shape" (Jsont.list Jsont.int) ··· 623 695 |> Jsont.Object.opt_mem "dimension_names" 624 696 (Jsont.list (Jsont.option Jsont.string)) 625 697 ~enc:(fun (t : Array_meta.t) -> t.dimension_names) 626 - |> Jsont.Object.opt_mem "storage_transformers" 627 - (Jsont.list Other_ext.jsont) 698 + |> Jsont.Object.opt_mem "storage_transformers" (Jsont.list Other_ext.jsont) 628 699 ~enc:(fun (t : Array_meta.t) -> t.storage_transformers) 629 - |> Jsont.Object.opt_mem "attributes" Jsont.json 630 - ~enc:(fun _ -> None) 631 - |> Jsont.Object.keep_unknown Jsont.json_mems 632 - ~enc:(fun (t : Array_meta.t) -> t.unknown) 700 + |> Jsont.Object.opt_mem "attributes" Jsont.json ~enc:(fun _ -> None) 701 + |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun (t : Array_meta.t) -> 702 + t.unknown) 633 703 |> Jsont.Object.finish 634 704 end 635 705 ··· 658 728 |> Jsont.Object.mem "cname" Jsont.string ~enc:(fun t -> t.cname) 659 729 |> Jsont.Object.mem "clevel" Jsont.int ~enc:(fun t -> t.clevel) 660 730 |> Jsont.Object.mem "shuffle" Jsont.int ~enc:(fun t -> t.shuffle) 661 - |> Jsont.Object.opt_mem "blocksize" Jsont.int ~enc:(fun t -> t.blocksize) 731 + |> Jsont.Object.opt_mem "blocksize" Jsont.int ~enc:(fun t -> 732 + t.blocksize) 662 733 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun t -> t.unknown) 663 734 |> Jsont.Object.finish 664 735 end 665 736 666 737 module Zlib = struct 667 - type t = { 668 - level : int; 669 - unknown : Jsont.json; 670 - } 738 + type t = { level : int; unknown : Jsont.json } 671 739 672 740 let level t = t.level 673 741 let unknown t = t.unknown 674 742 675 743 let jsont = 676 - Jsont.Object.map ~kind:"Zlib" 677 - (fun _id level unknown -> { level; unknown }) 744 + Jsont.Object.map ~kind:"Zlib" (fun _id level unknown -> 745 + { level; unknown }) 678 746 |> Jsont.Object.mem "id" Jsont.string ~enc:(fun _ -> "zlib") 679 747 |> Jsont.Object.mem "level" Jsont.int ~enc:(fun t -> t.level) 680 748 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun t -> t.unknown) ··· 682 750 end 683 751 end 684 752 685 - type compressor = [ 686 - | `Blosc of Compressor.Blosc.t 753 + type compressor = 754 + [ `Blosc of Compressor.Blosc.t 687 755 | `Zlib of Compressor.Zlib.t 688 - | `Other of Other_codec.t 689 - ] 756 + | `Other of Other_codec.t ] 690 757 691 758 let find_id mems = 692 - List.find_map (fun ((name, _), value) -> 693 - if name = "id" then 694 - match value with 695 - | Jsont.String (s, _) -> Some s 696 - | _ -> None 697 - else None) mems 759 + List.find_map 760 + (fun ((name, _), value) -> 761 + if name = "id" then 762 + match value with Jsont.String (s, _) -> Some s | _ -> None 763 + else None) 764 + mems 698 765 699 766 let compressor_jsont : compressor Jsont.t = 700 767 Jsont.map ~kind:"V2.Compressor" 701 768 ~dec:(fun json -> 702 769 match json with 703 - | Jsont.Object (mems, _meta) -> 704 - let id = find_id mems in 705 - (match id with 706 - | Some "blosc" -> `Blosc (jdec Compressor.Blosc.jsont json) 707 - | Some "zlib" -> `Zlib (jdec Compressor.Zlib.jsont json) 708 - | _ -> `Other (jdec Other_codec.jsont json)) 770 + | Jsont.Object (mems, _meta) -> ( 771 + let id = find_id mems in 772 + match id with 773 + | Some "blosc" -> `Blosc (jdec Compressor.Blosc.jsont json) 774 + | Some "zlib" -> `Zlib (jdec Compressor.Zlib.jsont json) 775 + | _ -> `Other (jdec Other_codec.jsont json)) 709 776 | _ -> Jsont.Error.msgf Jsont.Meta.none "V2.Compressor: expected object") 710 777 ~enc:(function 711 778 | `Blosc b -> jenc Compressor.Blosc.jsont b ··· 715 782 716 783 module Filter = struct 717 784 module Delta = struct 718 - type t = { 719 - dtype : string; 720 - astype : string option; 721 - unknown : Jsont.json; 722 - } 785 + type t = { dtype : string; astype : string option; unknown : Jsont.json } 723 786 724 787 let dtype t = t.dtype 725 788 let astype t = t.astype 726 789 let unknown t = t.unknown 727 790 728 791 let jsont = 729 - Jsont.Object.map ~kind:"Delta" 730 - (fun _id dtype astype unknown -> { dtype; astype; unknown }) 792 + Jsont.Object.map ~kind:"Delta" (fun _id dtype astype unknown -> 793 + { dtype; astype; unknown }) 731 794 |> Jsont.Object.mem "id" Jsont.string ~enc:(fun _ -> "delta") 732 795 |> Jsont.Object.mem "dtype" Jsont.string ~enc:(fun t -> t.dtype) 733 796 |> Jsont.Object.opt_mem "astype" Jsont.string ~enc:(fun t -> t.astype) ··· 736 799 end 737 800 end 738 801 739 - type filter = [ 740 - | `Delta of Filter.Delta.t 741 - | `Other of Other_codec.t 742 - ] 802 + type filter = [ `Delta of Filter.Delta.t | `Other of Other_codec.t ] 743 803 744 804 let filter_jsont : filter Jsont.t = 745 805 Jsont.map ~kind:"V2.Filter" 746 806 ~dec:(fun json -> 747 807 match json with 748 - | Jsont.Object (mems, _meta) -> 749 - let id = find_id mems in 750 - (match id with 751 - | Some "delta" -> `Delta (jdec Filter.Delta.jsont json) 752 - | _ -> `Other (jdec Other_codec.jsont json)) 808 + | Jsont.Object (mems, _meta) -> ( 809 + let id = find_id mems in 810 + match id with 811 + | Some "delta" -> `Delta (jdec Filter.Delta.jsont json) 812 + | _ -> `Other (jdec Other_codec.jsont json)) 753 813 | _ -> Jsont.Error.msgf Jsont.Meta.none "V2.Filter: expected object") 754 814 ~enc:(function 755 815 | `Delta d -> jenc Filter.Delta.jsont d ··· 768 828 dimension_separator : [ `Dot | `Slash ] option; 769 829 unknown : Jsont.json; 770 830 } 831 + 771 832 let shape t = t.shape 772 833 let chunks t = t.chunks 773 834 let dtype t = t.dtype ··· 780 841 end 781 842 782 843 let array_meta_jsont = 783 - let order_jsont = Jsont.enum ~kind:"order" ["C", `C; "F", `F] in 784 - let dim_sep_jsont = Jsont.enum ~kind:"dimension_separator" [".", `Dot; "/", `Slash] in 844 + let order_jsont = Jsont.enum ~kind:"order" [ ("C", `C); ("F", `F) ] in 845 + let dim_sep_jsont = 846 + Jsont.enum ~kind:"dimension_separator" [ (".", `Dot); ("/", `Slash) ] 847 + in 785 848 Jsont.Object.map ~kind:"V2.Array_meta" 786 849 (fun _zarr_format s c d comp fv ord filt dim_sep unk -> 787 - Array_meta.{ shape = s; chunks = c; dtype = d; compressor = comp; fill_value = fv; order = ord; filters = filt; dimension_separator = dim_sep; unknown = unk }) 850 + Array_meta. 851 + { 852 + shape = s; 853 + chunks = c; 854 + dtype = d; 855 + compressor = comp; 856 + fill_value = fv; 857 + order = ord; 858 + filters = filt; 859 + dimension_separator = dim_sep; 860 + unknown = unk; 861 + }) 788 862 |> Jsont.Object.mem "zarr_format" Jsont.int ~enc:(fun _ -> 2) 789 - |> Jsont.Object.mem "shape" (Jsont.list Jsont.int) ~enc:(fun (t : Array_meta.t) -> t.shape) 790 - |> Jsont.Object.mem "chunks" (Jsont.list Jsont.int) ~enc:(fun (t : Array_meta.t) -> t.chunks) 791 - |> Jsont.Object.mem "dtype" dtype_jsont ~enc:(fun (t : Array_meta.t) -> t.dtype) 792 - |> Jsont.Object.mem "compressor" (Jsont.option compressor_jsont) ~enc:(fun (t : Array_meta.t) -> t.compressor) 793 - |> Jsont.Object.mem "fill_value" fill_value_jsont ~enc:(fun (t : Array_meta.t) -> t.fill_value) 794 - |> Jsont.Object.mem "order" order_jsont ~enc:(fun (t : Array_meta.t) -> t.order) 795 - |> Jsont.Object.mem "filters" (Jsont.option (Jsont.list filter_jsont)) ~enc:(fun (t : Array_meta.t) -> t.filters) 796 - |> Jsont.Object.opt_mem "dimension_separator" dim_sep_jsont ~enc:(fun (t : Array_meta.t) -> t.dimension_separator) 797 - |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun (t : Array_meta.t) -> t.unknown) 863 + |> Jsont.Object.mem "shape" (Jsont.list Jsont.int) 864 + ~enc:(fun (t : Array_meta.t) -> t.shape) 865 + |> Jsont.Object.mem "chunks" (Jsont.list Jsont.int) 866 + ~enc:(fun (t : Array_meta.t) -> t.chunks) 867 + |> Jsont.Object.mem "dtype" dtype_jsont ~enc:(fun (t : Array_meta.t) -> 868 + t.dtype) 869 + |> Jsont.Object.mem "compressor" (Jsont.option compressor_jsont) 870 + ~enc:(fun (t : Array_meta.t) -> t.compressor) 871 + |> Jsont.Object.mem "fill_value" fill_value_jsont 872 + ~enc:(fun (t : Array_meta.t) -> t.fill_value) 873 + |> Jsont.Object.mem "order" order_jsont ~enc:(fun (t : Array_meta.t) -> 874 + t.order) 875 + |> Jsont.Object.mem "filters" 876 + (Jsont.option (Jsont.list filter_jsont)) 877 + ~enc:(fun (t : Array_meta.t) -> t.filters) 878 + |> Jsont.Object.opt_mem "dimension_separator" dim_sep_jsont 879 + ~enc:(fun (t : Array_meta.t) -> t.dimension_separator) 880 + |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun (t : Array_meta.t) -> 881 + t.unknown) 798 882 |> Jsont.Object.finish 799 883 end 800 884 ··· 820 904 { uuid; name; schema_url; spec_url; description }) 821 905 |> Jsont.Object.mem "uuid" Jsont.string ~enc:(fun t -> t.uuid) 822 906 |> Jsont.Object.mem "name" Jsont.string ~enc:(fun t -> t.name) 823 - |> Jsont.Object.opt_mem "schema_url" Jsont.string ~enc:(fun t -> t.schema_url) 907 + |> Jsont.Object.opt_mem "schema_url" Jsont.string ~enc:(fun t -> 908 + t.schema_url) 824 909 |> Jsont.Object.opt_mem "spec_url" Jsont.string ~enc:(fun t -> t.spec_url) 825 - |> Jsont.Object.opt_mem "description" Jsont.string ~enc:(fun t -> t.description) 826 - |> Jsont.Object.skip_unknown 827 - |> Jsont.Object.finish 910 + |> Jsont.Object.opt_mem "description" Jsont.string ~enc:(fun t -> 911 + t.description) 912 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 828 913 end 829 914 830 915 module Proj = struct ··· 838 923 let wkt2 t = t.wkt2 839 924 let projjson t = t.projjson 840 925 841 - let meta = { Meta. 842 - uuid = "f17cb550-5864-4468-aeb7-f3180cfb622f"; 843 - name = "proj:"; 844 - schema_url = Some "https://raw.githubusercontent.com/zarr-experimental/geo-proj/refs/tags/v1/schema.json"; 845 - spec_url = Some "https://github.com/zarr-experimental/geo-proj/blob/v1/README.md"; 846 - description = Some "Coordinate reference system information for geospatial data"; 847 - } 926 + let meta = 927 + { 928 + Meta.uuid = "f17cb550-5864-4468-aeb7-f3180cfb622f"; 929 + name = "proj:"; 930 + schema_url = 931 + Some 932 + "https://raw.githubusercontent.com/zarr-experimental/geo-proj/refs/tags/v1/schema.json"; 933 + spec_url = 934 + Some "https://github.com/zarr-experimental/geo-proj/blob/v1/README.md"; 935 + description = 936 + Some "Coordinate reference system information for geospatial data"; 937 + } 848 938 849 939 let jsont = 850 - Jsont.Object.map ~kind:"Conv.Proj" 851 - (fun code wkt2 projjson -> { code; wkt2; projjson }) 940 + Jsont.Object.map ~kind:"Conv.Proj" (fun code wkt2 projjson -> 941 + { code; wkt2; projjson }) 852 942 |> Jsont.Object.opt_mem "proj:code" Jsont.string ~enc:(fun t -> t.code) 853 943 |> Jsont.Object.opt_mem "proj:wkt2" Jsont.string ~enc:(fun t -> t.wkt2) 854 - |> Jsont.Object.opt_mem "proj:projjson" Jsont.json ~enc:(fun t -> t.projjson) 855 - |> Jsont.Object.skip_unknown 856 - |> Jsont.Object.finish 944 + |> Jsont.Object.opt_mem "proj:projjson" Jsont.json ~enc:(fun t -> 945 + t.projjson) 946 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 857 947 end 858 948 859 949 module Spatial = struct ··· 873 963 let shape t = t.shape 874 964 let registration t = t.registration 875 965 876 - let meta = { Meta. 877 - uuid = "689b58e2-cf7b-45e0-9fff-9cfc0883d6b4"; 878 - name = "spatial:"; 879 - schema_url = Some "https://raw.githubusercontent.com/zarr-conventions/spatial/refs/tags/v1/schema.json"; 880 - spec_url = Some "https://github.com/zarr-conventions/spatial/blob/v1/README.md"; 881 - description = Some "Spatial coordinate information"; 882 - } 966 + let meta = 967 + { 968 + Meta.uuid = "689b58e2-cf7b-45e0-9fff-9cfc0883d6b4"; 969 + name = "spatial:"; 970 + schema_url = 971 + Some 972 + "https://raw.githubusercontent.com/zarr-conventions/spatial/refs/tags/v1/schema.json"; 973 + spec_url = 974 + Some "https://github.com/zarr-conventions/spatial/blob/v1/README.md"; 975 + description = Some "Spatial coordinate information"; 976 + } 883 977 884 978 let jsont = 885 - let registration_jsont = Jsont.enum ~kind:"registration" ["pixel", `Pixel; "node", `Node] in 979 + let registration_jsont = 980 + Jsont.enum ~kind:"registration" [ ("pixel", `Pixel); ("node", `Node) ] 981 + in 886 982 Jsont.Object.map ~kind:"Conv.Spatial" 887 983 (fun dimensions bbox transform_type transform shape registration -> 888 984 { dimensions; bbox; transform_type; transform; shape; registration }) 889 - |> Jsont.Object.mem "spatial:dimensions" (Jsont.list Jsont.string) ~enc:(fun t -> t.dimensions) 890 - |> Jsont.Object.opt_mem "spatial:bbox" (Jsont.list Jsont.number) ~enc:(fun t -> t.bbox) 891 - |> Jsont.Object.opt_mem "spatial:transform_type" Jsont.string ~enc:(fun t -> t.transform_type) 892 - |> Jsont.Object.opt_mem "spatial:transform" (Jsont.list Jsont.number) ~enc:(fun t -> t.transform) 893 - |> Jsont.Object.opt_mem "spatial:shape" (Jsont.list Jsont.int) ~enc:(fun t -> t.shape) 894 - |> Jsont.Object.opt_mem "spatial:registration" registration_jsont ~enc:(fun t -> t.registration) 895 - |> Jsont.Object.skip_unknown 896 - |> Jsont.Object.finish 985 + |> Jsont.Object.mem "spatial:dimensions" (Jsont.list Jsont.string) 986 + ~enc:(fun t -> t.dimensions) 987 + |> Jsont.Object.opt_mem "spatial:bbox" (Jsont.list Jsont.number) 988 + ~enc:(fun t -> t.bbox) 989 + |> Jsont.Object.opt_mem "spatial:transform_type" Jsont.string 990 + ~enc:(fun t -> t.transform_type) 991 + |> Jsont.Object.opt_mem "spatial:transform" (Jsont.list Jsont.number) 992 + ~enc:(fun t -> t.transform) 993 + |> Jsont.Object.opt_mem "spatial:shape" (Jsont.list Jsont.int) 994 + ~enc:(fun t -> t.shape) 995 + |> Jsont.Object.opt_mem "spatial:registration" registration_jsont 996 + ~enc:(fun t -> t.registration) 997 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 897 998 end 898 999 899 1000 module Geoemb = struct ··· 905 1006 grid_id : string option; 906 1007 grid_definition : string option; 907 1008 } 1009 + 908 1010 let layout_type t = t.layout_type 909 1011 let chip_size t = t.chip_size 910 1012 let stride t = t.stride 911 1013 let grid_id t = t.grid_id 912 1014 let grid_definition t = t.grid_definition 913 1015 914 - let layout_type_jsont = Jsont.enum ~kind:"layout_type" 915 - ["regular_grid", `Regular_grid; "irregular", `Irregular] 1016 + let layout_type_jsont = 1017 + Jsont.enum ~kind:"layout_type" 1018 + [ ("regular_grid", `Regular_grid); ("irregular", `Irregular) ] 916 1019 917 1020 let int_pair = 918 1021 Jsont.t2 ~kind:"int_pair" ··· 921 1024 Jsont.int 922 1025 923 1026 let jsont = 924 - Jsont.Object.map ~kind:"Chip_layout" 925 - (fun lt cs st gi gd -> { layout_type = lt; chip_size = cs; 926 - stride = st; grid_id = gi; 927 - grid_definition = gd }) 928 - |> Jsont.Object.mem "layout_type" layout_type_jsont 929 - ~enc:(fun t -> t.layout_type) 1027 + Jsont.Object.map ~kind:"Chip_layout" (fun lt cs st gi gd -> 1028 + { 1029 + layout_type = lt; 1030 + chip_size = cs; 1031 + stride = st; 1032 + grid_id = gi; 1033 + grid_definition = gd; 1034 + }) 1035 + |> Jsont.Object.mem "layout_type" layout_type_jsont ~enc:(fun t -> 1036 + t.layout_type) 930 1037 |> Jsont.Object.mem "chip_size" int_pair ~enc:(fun t -> t.chip_size) 931 1038 |> Jsont.Object.opt_mem "stride" int_pair ~enc:(fun t -> t.stride) 932 1039 |> Jsont.Object.opt_mem "grid_id" Jsont.string ~enc:(fun t -> t.grid_id) 933 - |> Jsont.Object.opt_mem "grid_definition" Jsont.string 934 - ~enc:(fun t -> t.grid_definition) 935 - |> Jsont.Object.skip_unknown 936 - |> Jsont.Object.finish 1040 + |> Jsont.Object.opt_mem "grid_definition" Jsont.string ~enc:(fun t -> 1041 + t.grid_definition) 1042 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 937 1043 end 938 1044 939 1045 module Scale = struct 940 1046 module Scalar = struct 941 1047 type t = { scale : float; offset : float } 1048 + 942 1049 let scale t = t.scale 943 1050 let offset t = t.offset 1051 + 944 1052 let jsont = 945 - Jsont.Object.map ~kind:"Scale.Scalar" 946 - (fun scale offset -> 1053 + Jsont.Object.map ~kind:"Scale.Scalar" (fun scale offset -> 947 1054 { scale; offset = Option.value ~default:0.0 offset }) 948 1055 |> Jsont.Object.mem "scale" Jsont.number ~enc:(fun t -> t.scale) 949 - |> Jsont.Object.opt_mem "offset" Jsont.number 950 - ~enc:(fun t -> 951 - if t.offset = 0.0 then None else Some t.offset) 952 - |> Jsont.Object.skip_unknown 953 - |> Jsont.Object.finish 1056 + |> Jsont.Object.opt_mem "offset" Jsont.number ~enc:(fun t -> 1057 + if t.offset = 0.0 then None else Some t.offset) 1058 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 954 1059 end 1060 + 955 1061 module Array_ = struct 956 1062 type t = { array_name : string; nodata : string option } 1063 + 957 1064 let array_name t = t.array_name 958 1065 let nodata t = t.nodata 1066 + 959 1067 let nodata_jsont = 960 - let from_string = Jsont.map ~kind:"nodata" 961 - ~dec:Fun.id ~enc:Fun.id Jsont.string in 962 - let from_number = Jsont.map ~kind:"nodata" 963 - ~dec:(fun f -> Printf.sprintf "%g" f) 964 - ~enc:(fun _ -> 0.0) 965 - Jsont.number in 966 - Jsont.any ~kind:"nodata" 967 - ~dec_string:from_string ~dec_number:from_number 968 - ~enc:(fun _ -> from_string) () 1068 + let from_string = 1069 + Jsont.map ~kind:"nodata" ~dec:Fun.id ~enc:Fun.id Jsont.string 1070 + in 1071 + let from_number = 1072 + Jsont.map ~kind:"nodata" 1073 + ~dec:(fun f -> Printf.sprintf "%g" f) 1074 + ~enc:(fun _ -> 0.0) 1075 + Jsont.number 1076 + in 1077 + Jsont.any ~kind:"nodata" ~dec_string:from_string 1078 + ~dec_number:from_number 1079 + ~enc:(fun _ -> from_string) 1080 + () 1081 + 969 1082 let jsont = 970 - Jsont.Object.map ~kind:"Scale.Array" 971 - (fun array_name nodata -> { array_name; nodata }) 972 - |> Jsont.Object.mem "array_name" Jsont.string 973 - ~enc:(fun t -> t.array_name) 974 - |> Jsont.Object.opt_mem "nodata" nodata_jsont 975 - ~enc:(fun t -> t.nodata) 976 - |> Jsont.Object.skip_unknown 977 - |> Jsont.Object.finish 1083 + Jsont.Object.map ~kind:"Scale.Array" (fun array_name nodata -> 1084 + { array_name; nodata }) 1085 + |> Jsont.Object.mem "array_name" Jsont.string ~enc:(fun t -> 1086 + t.array_name) 1087 + |> Jsont.Object.opt_mem "nodata" nodata_jsont ~enc:(fun t -> t.nodata) 1088 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 978 1089 end 1090 + 979 1091 type t = [ `Scalar of Scalar.t | `Array of Array_.t ] 980 1092 981 1093 let jsont = 982 - let scalar = Jsont.Object.Case.map ~dec:(fun s -> `Scalar s) 983 - "scalar" Scalar.jsont in 984 - let array_ = Jsont.Object.Case.map ~dec:(fun a -> `Array a) 985 - "array" Array_.jsont in 1094 + let scalar = 1095 + Jsont.Object.Case.map ~dec:(fun s -> `Scalar s) "scalar" Scalar.jsont 1096 + in 1097 + let array_ = 1098 + Jsont.Object.Case.map ~dec:(fun a -> `Array a) "array" Array_.jsont 1099 + in 986 1100 let enc_case = function 987 1101 | `Scalar s -> Jsont.Object.Case.value scalar s 988 1102 | `Array a -> Jsont.Object.Case.value array_ a 989 1103 in 990 1104 Jsont.Object.map ~kind:"Scale" Fun.id 991 - |> Jsont.Object.case_mem "type" Jsont.string 992 - ~enc:Fun.id ~enc_case 1105 + |> Jsont.Object.case_mem "type" Jsont.string ~enc:Fun.id ~enc_case 993 1106 ~tag_to_string:Fun.id ~tag_compare:String.compare 994 - Jsont.Object.Case.[make scalar; make array_] 1107 + Jsont.Object.Case.[ make scalar; make array_ ] 995 1108 |> Jsont.Object.finish 996 1109 end 997 1110 ··· 1003 1116 scale : Scale.t option; 1004 1117 link : string option; 1005 1118 } 1119 + 1006 1120 let meth t = t.meth 1007 1121 let original_dtype t = t.original_dtype 1008 1122 let quantized_dtype t = t.quantized_dtype 1009 1123 let scale t = t.scale 1010 1124 let link t = t.link 1125 + 1011 1126 let jsont = 1012 - Jsont.Object.map ~kind:"Quantization" 1013 - (fun m od qd sc lk -> 1014 - { meth = m; original_dtype = od; quantized_dtype = qd; 1015 - scale = sc; link = lk }) 1127 + Jsont.Object.map ~kind:"Quantization" (fun m od qd sc lk -> 1128 + { 1129 + meth = m; 1130 + original_dtype = od; 1131 + quantized_dtype = qd; 1132 + scale = sc; 1133 + link = lk; 1134 + }) 1016 1135 |> Jsont.Object.mem "method" Jsont.string ~enc:(fun t -> t.meth) 1017 - |> Jsont.Object.mem "original_dtype" Jsont.string 1018 - ~enc:(fun t -> t.original_dtype) 1019 - |> Jsont.Object.opt_mem "quantized_dtype" Jsont.string 1020 - ~enc:(fun t -> t.quantized_dtype) 1136 + |> Jsont.Object.mem "original_dtype" Jsont.string ~enc:(fun t -> 1137 + t.original_dtype) 1138 + |> Jsont.Object.opt_mem "quantized_dtype" Jsont.string ~enc:(fun t -> 1139 + t.quantized_dtype) 1021 1140 |> Jsont.Object.opt_mem "scale" Scale.jsont ~enc:(fun t -> t.scale) 1022 1141 |> Jsont.Object.opt_mem "link" Jsont.string ~enc:(fun t -> t.link) 1023 - |> Jsont.Object.skip_unknown 1024 - |> Jsont.Object.finish 1142 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 1025 1143 end 1026 1144 1027 1145 type t = { ··· 1037 1155 build_version : string option; 1038 1156 benchmark : string list option; 1039 1157 } 1158 + 1040 1159 let type_ t = t.type_ 1041 1160 let dimensions t = t.dimensions 1042 1161 let model t = t.model ··· 1049 1168 let build_version t = t.build_version 1050 1169 let benchmark t = t.benchmark 1051 1170 1052 - let meta = { Meta. 1053 - uuid = "61c12cc5-0e28-4056-999a-480cf3fb7e4c"; 1054 - name = "geoemb:"; 1055 - schema_url = Some "https://raw.githubusercontent.com/geo-embeddings/embeddings-zarr-convention/refs/tags/v1/schema.json"; 1056 - spec_url = Some "https://github.com/geo-embeddings/embeddings-zarr-convention/blob/v1/README.md"; 1057 - description = Some "Geoembeddings convention for geospatial embedding arrays with model provenance"; 1058 - } 1171 + let meta = 1172 + { 1173 + Meta.uuid = "61c12cc5-0e28-4056-999a-480cf3fb7e4c"; 1174 + name = "geoemb:"; 1175 + schema_url = 1176 + Some 1177 + "https://raw.githubusercontent.com/geo-embeddings/embeddings-zarr-convention/refs/tags/v1/schema.json"; 1178 + spec_url = 1179 + Some 1180 + "https://github.com/geo-embeddings/embeddings-zarr-convention/blob/v1/README.md"; 1181 + description = 1182 + Some 1183 + "Geoembeddings convention for geospatial embedding arrays with \ 1184 + model provenance"; 1185 + } 1059 1186 1060 - let type_jsont = Jsont.enum ~kind:"geoemb_type" ["pixel", `Pixel; "chip", `Chip] 1187 + let type_jsont = 1188 + Jsont.enum ~kind:"geoemb_type" [ ("pixel", `Pixel); ("chip", `Chip) ] 1061 1189 1062 1190 let jsont = 1063 1191 Jsont.Object.map ~kind:"Geoemb" 1064 1192 (fun ty dim mdl src dt gsd cl qu sl bv bm -> 1065 - { type_ = ty; dimensions = dim; model = mdl; source_data = src; 1066 - data_type = dt; gsd; chip_layout = cl; quantization = qu; 1067 - spatial_layout = sl; build_version = bv; benchmark = bm }) 1193 + { 1194 + type_ = ty; 1195 + dimensions = dim; 1196 + model = mdl; 1197 + source_data = src; 1198 + data_type = dt; 1199 + gsd; 1200 + chip_layout = cl; 1201 + quantization = qu; 1202 + spatial_layout = sl; 1203 + build_version = bv; 1204 + benchmark = bm; 1205 + }) 1068 1206 |> Jsont.Object.mem "geoemb:type" type_jsont ~enc:(fun t -> t.type_) 1069 - |> Jsont.Object.mem "geoemb:dimensions" Jsont.int 1070 - ~enc:(fun t -> t.dimensions) 1207 + |> Jsont.Object.mem "geoemb:dimensions" Jsont.int ~enc:(fun t -> 1208 + t.dimensions) 1071 1209 |> Jsont.Object.mem "geoemb:model" Jsont.string ~enc:(fun t -> t.model) 1072 1210 |> Jsont.Object.mem "geoemb:source_data" (Jsont.list Jsont.string) 1073 1211 ~enc:(fun t -> t.source_data) 1074 - |> Jsont.Object.mem "geoemb:data_type" Jsont.string 1075 - ~enc:(fun t -> t.data_type) 1212 + |> Jsont.Object.mem "geoemb:data_type" Jsont.string ~enc:(fun t -> 1213 + t.data_type) 1076 1214 |> Jsont.Object.opt_mem "geoemb:gsd" Jsont.number ~enc:(fun t -> t.gsd) 1077 1215 |> Jsont.Object.opt_mem "geoemb:chip_layout" Chip_layout.jsont 1078 1216 ~enc:(fun t -> t.chip_layout) ··· 1080 1218 ~enc:(fun t -> t.quantization) 1081 1219 |> Jsont.Object.opt_mem "geoemb:spatial_layout" Jsont.string 1082 1220 ~enc:(fun t -> t.spatial_layout) 1083 - |> Jsont.Object.opt_mem "geoemb:build_version" Jsont.string 1084 - ~enc:(fun t -> t.build_version) 1221 + |> Jsont.Object.opt_mem "geoemb:build_version" Jsont.string ~enc:(fun t -> 1222 + t.build_version) 1085 1223 |> Jsont.Object.opt_mem "geoemb:benchmark" (Jsont.list Jsont.string) 1086 1224 ~enc:(fun t -> t.benchmark) 1087 - |> Jsont.Object.skip_unknown 1088 - |> Jsont.Object.finish 1225 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 1089 1226 end 1090 1227 1091 1228 module Multiscales = struct ··· 1103 1240 let jsont = 1104 1241 Jsont.Object.map ~kind:"Conv.Multiscales.Transform" 1105 1242 (fun scale translation unknown -> { scale; translation; unknown }) 1106 - |> Jsont.Object.opt_mem "scale" (Jsont.list Jsont.number) ~enc:(fun t -> t.scale) 1107 - |> Jsont.Object.opt_mem "translation" (Jsont.list Jsont.number) ~enc:(fun t -> t.translation) 1243 + |> Jsont.Object.opt_mem "scale" (Jsont.list Jsont.number) ~enc:(fun t -> 1244 + t.scale) 1245 + |> Jsont.Object.opt_mem "translation" (Jsont.list Jsont.number) 1246 + ~enc:(fun t -> t.translation) 1108 1247 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun t -> t.unknown) 1109 1248 |> Jsont.Object.finish 1110 1249 end ··· 1129 1268 (fun asset derived_from transform resampling_method unknown -> 1130 1269 { asset; derived_from; transform; resampling_method; unknown }) 1131 1270 |> Jsont.Object.mem "asset" Jsont.string ~enc:(fun t -> t.asset) 1132 - |> Jsont.Object.opt_mem "derived_from" Jsont.string ~enc:(fun t -> t.derived_from) 1133 - |> Jsont.Object.opt_mem "transform" Transform.jsont ~enc:(fun t -> t.transform) 1134 - |> Jsont.Object.opt_mem "resampling_method" Jsont.string ~enc:(fun t -> t.resampling_method) 1271 + |> Jsont.Object.opt_mem "derived_from" Jsont.string ~enc:(fun t -> 1272 + t.derived_from) 1273 + |> Jsont.Object.opt_mem "transform" Transform.jsont ~enc:(fun t -> 1274 + t.transform) 1275 + |> Jsont.Object.opt_mem "resampling_method" Jsont.string ~enc:(fun t -> 1276 + t.resampling_method) 1135 1277 |> Jsont.Object.keep_unknown Jsont.json_mems ~enc:(fun t -> t.unknown) 1136 1278 |> Jsont.Object.finish 1137 1279 end 1138 1280 1139 - type t = { 1140 - layout : Layout_item.t list; 1141 - resampling_method : string option; 1142 - } 1281 + type t = { layout : Layout_item.t list; resampling_method : string option } 1143 1282 1144 1283 let layout t = t.layout 1145 1284 let resampling_method t = t.resampling_method 1146 1285 1147 - let meta = { Meta. 1148 - uuid = "d35379db-88df-4056-af3a-620245f8e347"; 1149 - name = "multiscales"; 1150 - schema_url = Some "https://raw.githubusercontent.com/zarr-conventions/multiscales/refs/tags/v1/schema.json"; 1151 - spec_url = Some "https://github.com/zarr-conventions/multiscales/blob/v1/README.md"; 1152 - description = Some "Multiscale layout of zarr datasets"; 1153 - } 1286 + let meta = 1287 + { 1288 + Meta.uuid = "d35379db-88df-4056-af3a-620245f8e347"; 1289 + name = "multiscales"; 1290 + schema_url = 1291 + Some 1292 + "https://raw.githubusercontent.com/zarr-conventions/multiscales/refs/tags/v1/schema.json"; 1293 + spec_url = 1294 + Some 1295 + "https://github.com/zarr-conventions/multiscales/blob/v1/README.md"; 1296 + description = Some "Multiscale layout of zarr datasets"; 1297 + } 1154 1298 1155 1299 let jsont = 1156 - Jsont.Object.map ~kind:"Conv.Multiscales" 1157 - (fun layout resampling_method -> { layout; resampling_method }) 1158 - |> Jsont.Object.mem "layout" (Jsont.list Layout_item.jsont) ~enc:(fun t -> t.layout) 1159 - |> Jsont.Object.opt_mem "resampling_method" Jsont.string ~enc:(fun t -> t.resampling_method) 1160 - |> Jsont.Object.skip_unknown 1161 - |> Jsont.Object.finish 1300 + Jsont.Object.map ~kind:"Conv.Multiscales" (fun layout resampling_method -> 1301 + { layout; resampling_method }) 1302 + |> Jsont.Object.mem "layout" (Jsont.list Layout_item.jsont) ~enc:(fun t -> 1303 + t.layout) 1304 + |> Jsont.Object.opt_mem "resampling_method" Jsont.string ~enc:(fun t -> 1305 + t.resampling_method) 1306 + |> Jsont.Object.skip_unknown |> Jsont.Object.finish 1162 1307 end 1163 1308 end 1164 1309 ··· 1171 1316 geoemb : Conv.Geoemb.t option; 1172 1317 unknown : Jsont.json; 1173 1318 } 1319 + 1174 1320 let conventions t = t.conventions 1175 1321 let proj t = t.proj 1176 1322 let spatial t = t.spatial 1177 1323 let multiscales t = t.multiscales 1178 1324 let geoemb t = t.geoemb 1179 1325 let unknown t = t.unknown 1180 - let empty = { 1181 - conventions = []; proj = None; spatial = None; multiscales = None; 1182 - geoemb = None; unknown = Jsont.Json.object' []; 1183 - } 1326 + 1327 + let empty = 1328 + { 1329 + conventions = []; 1330 + proj = None; 1331 + spatial = None; 1332 + multiscales = None; 1333 + geoemb = None; 1334 + unknown = Jsont.Json.object' []; 1335 + } 1184 1336 end 1185 1337 1186 1338 let emit_prefixed prefix conv_jsont value add = 1187 1339 match value with 1188 1340 | None -> () 1189 - | Some v -> 1190 - match Jsont.Json.encode conv_jsont v with 1191 - | Ok (Jsont.Object (ms, _)) -> 1192 - List.iter (fun ((k, _), _ as m) -> 1193 - if String.length k > String.length prefix 1194 - && String.sub k 0 (String.length prefix) = prefix 1195 - then add m) ms 1196 - | _ -> () 1341 + | Some v -> ( 1342 + match Jsont.Json.encode conv_jsont v with 1343 + | Ok (Jsont.Object (ms, _)) -> 1344 + List.iter 1345 + (fun (((k, _), _) as m) -> 1346 + if 1347 + String.length k > String.length prefix 1348 + && String.sub k 0 (String.length prefix) = prefix 1349 + then add m) 1350 + ms 1351 + | _ -> ()) 1197 1352 1198 1353 let attrs_jsont : Attrs.t Jsont.t = 1199 1354 Jsont.map ~kind:"Attrs" 1200 1355 ~dec:(fun json -> 1201 - let mems = match json with 1202 - | Jsont.Object (mems, _) -> mems 1203 - | _ -> [] 1204 - in 1356 + let mems = match json with Jsont.Object (mems, _) -> mems | _ -> [] in 1205 1357 let find_mem name = 1206 - List.find_map (fun ((k, _), v) -> 1207 - if k = name then Some v else None) mems 1358 + List.find_map 1359 + (fun ((k, _), v) -> if k = name then Some v else None) 1360 + mems 1208 1361 in 1209 1362 let is_known ((k, _), _) = 1210 - k = "zarr_conventions" || k = "multiscales" || 1211 - (String.length k > 5 && String.sub k 0 5 = "proj:") || 1212 - (String.length k > 8 && String.sub k 0 8 = "spatial:") || 1213 - (String.length k > 7 && String.sub k 0 7 = "geoemb:") 1363 + k = "zarr_conventions" || k = "multiscales" 1364 + || (String.length k > 5 && String.sub k 0 5 = "proj:") 1365 + || (String.length k > 8 && String.sub k 0 8 = "spatial:") 1366 + || (String.length k > 7 && String.sub k 0 7 = "geoemb:") 1214 1367 in 1215 1368 (* zarr_conventions *) 1216 - let convs = match find_mem "zarr_conventions" with 1217 - | Some arr -> 1218 - (match Jsont.Json.decode (Jsont.list Conv.Meta.jsont) arr with 1219 - | Ok cs -> cs | Error _ -> []) 1369 + let convs = 1370 + match find_mem "zarr_conventions" with 1371 + | Some arr -> ( 1372 + match Jsont.Json.decode (Jsont.list Conv.Meta.jsont) arr with 1373 + | Ok cs -> cs 1374 + | Error _ -> []) 1220 1375 | None -> [] 1221 1376 in 1222 1377 (* proj: try decoding if any proj: key exists *) 1223 - let has_proj = List.exists (fun ((k, _), _) -> 1224 - String.length k > 5 && String.sub k 0 5 = "proj:") mems 1378 + let has_proj = 1379 + List.exists 1380 + (fun ((k, _), _) -> String.length k > 5 && String.sub k 0 5 = "proj:") 1381 + mems 1225 1382 in 1226 1383 let proj_val = 1227 1384 if has_proj then 1228 1385 match Jsont.Json.decode Conv.Proj.jsont json with 1229 - | Ok p when Conv.Proj.code p <> None || Conv.Proj.wkt2 p <> None || Conv.Proj.projjson p <> None -> Some p 1386 + | Ok p 1387 + when Conv.Proj.code p <> None 1388 + || Conv.Proj.wkt2 p <> None 1389 + || Conv.Proj.projjson p <> None -> 1390 + Some p 1230 1391 | _ -> None 1231 1392 else None 1232 1393 in 1233 1394 (* spatial: need spatial:dimensions to be present (it's required) *) 1234 - let has_spatial = List.exists (fun ((k, _), _) -> k = "spatial:dimensions") mems in 1395 + let has_spatial = 1396 + List.exists (fun ((k, _), _) -> k = "spatial:dimensions") mems 1397 + in 1235 1398 let spatial_val = 1236 1399 if has_spatial then 1237 1400 match Jsont.Json.decode Conv.Spatial.jsont json with 1238 - | Ok s -> Some s | Error _ -> None 1401 + | Ok s -> Some s 1402 + | Error _ -> None 1239 1403 else None 1240 1404 in 1241 1405 (* multiscales: it's a nested object at key "multiscales" *) 1242 - let multiscales_val = match find_mem "multiscales" with 1243 - | Some ms_json -> 1244 - (match Jsont.Json.decode Conv.Multiscales.jsont ms_json with 1245 - | Ok m -> Some m | Error _ -> None) 1406 + let multiscales_val = 1407 + match find_mem "multiscales" with 1408 + | Some ms_json -> ( 1409 + match Jsont.Json.decode Conv.Multiscales.jsont ms_json with 1410 + | Ok m -> Some m 1411 + | Error _ -> None) 1246 1412 | None -> None 1247 1413 in 1248 1414 (* geoemb: prefixed keys *) 1249 - let has_geoemb = List.exists (fun ((k, _), _) -> 1250 - k = "geoemb:type") mems in 1415 + let has_geoemb = 1416 + List.exists (fun ((k, _), _) -> k = "geoemb:type") mems 1417 + in 1251 1418 let geoemb_val = 1252 1419 if has_geoemb then 1253 1420 match Jsont.Json.decode Conv.Geoemb.jsont json with 1254 - | Ok g -> Some g | Error _ -> None 1421 + | Ok g -> Some g 1422 + | Error _ -> None 1255 1423 else None 1256 1424 in 1257 1425 (* unknown: everything that's not a known convention key *) 1258 1426 let unknown_mems = List.filter (fun m -> not (is_known m)) mems in 1259 1427 let unknown_val = Jsont.Json.object' unknown_mems in 1260 - { Attrs. 1261 - conventions = convs; 1428 + { 1429 + Attrs.conventions = convs; 1262 1430 proj = proj_val; 1263 1431 spatial = spatial_val; 1264 1432 multiscales = multiscales_val; ··· 1270 1438 let add m = mems := m :: !mems in 1271 1439 (* Auto-populate zarr_conventions *) 1272 1440 let conv_metas = 1273 - (match t.geoemb with Some _ -> [Conv.Geoemb.meta] | None -> []) @ 1274 - (match t.proj with Some _ -> [Conv.Proj.meta] | None -> []) @ 1275 - (match t.spatial with Some _ -> [Conv.Spatial.meta] | None -> []) @ 1276 - (match t.multiscales with Some _ -> [Conv.Multiscales.meta] | None -> []) 1441 + (match t.geoemb with Some _ -> [ Conv.Geoemb.meta ] | None -> []) 1442 + @ (match t.proj with Some _ -> [ Conv.Proj.meta ] | None -> []) 1443 + @ (match t.spatial with Some _ -> [ Conv.Spatial.meta ] | None -> []) 1444 + @ 1445 + match t.multiscales with 1446 + | Some _ -> [ Conv.Multiscales.meta ] 1447 + | None -> [] 1277 1448 in 1278 1449 if conv_metas <> [] then begin 1279 1450 match Jsont.Json.encode (Jsont.list Conv.Meta.jsont) conv_metas with ··· 1284 1455 emit_prefixed "spatial:" Conv.Spatial.jsont t.spatial add; 1285 1456 (* multiscales *) 1286 1457 (match t.multiscales with 1287 - | Some m -> 1288 - (match Jsont.Json.encode Conv.Multiscales.jsont m with 1458 + | Some m -> ( 1459 + match Jsont.Json.encode Conv.Multiscales.jsont m with 1289 1460 | Ok j -> add (("multiscales", Jsont.Meta.none), j) 1290 1461 | _ -> ()) 1291 - | None -> ()); 1462 + | None -> ()); 1292 1463 emit_prefixed "geoemb:" Conv.Geoemb.jsont t.geoemb add; 1293 1464 (* unknown *) 1294 1465 (match t.unknown with 1295 - | Jsont.Object (unk_mems, _) -> List.iter add unk_mems 1296 - | _ -> ()); 1466 + | Jsont.Object (unk_mems, _) -> List.iter add unk_mems 1467 + | _ -> ()); 1297 1468 Jsont.Json.object' (List.rev !mems)) 1298 1469 Jsont.json 1299 1470 ··· 1303 1474 attrs : Attrs.t; 1304 1475 unknown : Jsont.json; 1305 1476 } 1477 + 1306 1478 let kind t = t.kind 1307 1479 let attrs t = t.attrs 1308 1480 let unknown t = t.unknown ··· 1314 1486 attrs : Attrs.t; 1315 1487 unknown : Jsont.json; 1316 1488 } 1489 + 1317 1490 let kind t = t.kind 1318 1491 let attrs t = t.attrs 1319 1492 let unknown t = t.unknown ··· 1322 1495 let v2_array_jsont : V2_node.t Jsont.t = 1323 1496 Jsont.map ~kind:"V2.Array" 1324 1497 ~dec:(fun meta -> 1325 - V2_node.{ 1326 - kind = `Array meta; 1327 - attrs = Attrs.empty; 1328 - unknown = Jsont.Json.object' []; 1329 - }) 1498 + V2_node. 1499 + { 1500 + kind = `Array meta; 1501 + attrs = Attrs.empty; 1502 + unknown = Jsont.Json.object' []; 1503 + }) 1330 1504 ~enc:(fun t -> 1331 1505 match t.V2_node.kind with 1332 1506 | `Array a -> a 1333 - | `Group -> Jsont.Error.msgf Jsont.Meta.none "v2_array_jsont: not an array") 1507 + | `Group -> 1508 + Jsont.Error.msgf Jsont.Meta.none "v2_array_jsont: not an array") 1334 1509 V2.array_meta_jsont 1335 1510 1336 1511 let v2_group_jsont : V2_node.t Jsont.t = 1337 1512 Jsont.map ~kind:"V2.Group" 1338 1513 ~dec:(fun _json -> 1339 - V2_node.{ 1340 - kind = `Group; 1341 - attrs = Attrs.empty; 1342 - unknown = Jsont.Json.object' []; 1343 - }) 1514 + V2_node. 1515 + { kind = `Group; attrs = Attrs.empty; unknown = Jsont.Json.object' [] }) 1344 1516 ~enc:(fun _t -> 1345 - Jsont.Json.object' [ 1346 - (("zarr_format", Jsont.Meta.none), Jsont.Json.number 2.0); 1347 - ]) 1517 + Jsont.Json.object' 1518 + [ (("zarr_format", Jsont.Meta.none), Jsont.Json.number 2.0) ]) 1348 1519 Jsont.json 1349 1520 1350 1521 let v3_jsont : V3_node.t Jsont.t = ··· 1353 1524 in 1354 1525 Jsont.map ~kind:"V3.Node" 1355 1526 ~dec:(fun json -> 1356 - let mems = match json with 1527 + let mems = 1528 + match json with 1357 1529 | Jsont.Object (m, _) -> m 1358 1530 | _ -> Jsont.Error.msgf Jsont.Meta.none "v3_jsont: expected object" 1359 1531 in 1360 - let node_type = match find_mem mems "node_type" with 1532 + let node_type = 1533 + match find_mem mems "node_type" with 1361 1534 | Some (Jsont.String (s, _)) -> s 1362 1535 | _ -> Jsont.Error.msgf Jsont.Meta.none "v3_jsont: missing node_type" 1363 1536 in 1364 1537 let attrs_val = 1365 1538 match find_mem mems "attributes" with 1366 - | Some attrs_json -> 1367 - (match Jsont.Json.decode attrs_jsont attrs_json with 1368 - | Ok a -> a 1369 - | Error _ -> Attrs.empty) 1539 + | Some attrs_json -> ( 1540 + match Jsont.Json.decode attrs_jsont attrs_json with 1541 + | Ok a -> a 1542 + | Error _ -> Attrs.empty) 1370 1543 | None -> Attrs.empty 1371 1544 in 1372 1545 (* unknown: everything except the standard V3 node-level keys *) 1373 - let standard_keys = [ 1374 - "zarr_format"; "node_type"; "shape"; "data_type"; 1375 - "chunk_grid"; "chunk_key_encoding"; "codecs"; "fill_value"; 1376 - "dimension_names"; "storage_transformers"; "attributes"; 1377 - ] in 1378 - let unknown_mems = List.filter 1379 - (fun ((k, _), _) -> not (List.mem k standard_keys)) mems 1546 + let standard_keys = 1547 + [ 1548 + "zarr_format"; 1549 + "node_type"; 1550 + "shape"; 1551 + "data_type"; 1552 + "chunk_grid"; 1553 + "chunk_key_encoding"; 1554 + "codecs"; 1555 + "fill_value"; 1556 + "dimension_names"; 1557 + "storage_transformers"; 1558 + "attributes"; 1559 + ] 1560 + in 1561 + let unknown_mems = 1562 + List.filter (fun ((k, _), _) -> not (List.mem k standard_keys)) mems 1380 1563 in 1381 1564 let unknown_val = Jsont.Json.object' unknown_mems in 1382 - (match node_type with 1383 - | "array" -> 1384 - let arr = jdec V3.array_meta_jsont json in 1385 - V3_node.{ kind = `Array arr; attrs = attrs_val; unknown = unknown_val } 1386 - | "group" -> 1387 - V3_node.{ kind = `Group; attrs = attrs_val; unknown = unknown_val } 1388 - | s -> Jsont.Error.msgf Jsont.Meta.none "v3_jsont: unknown node_type: %s" s)) 1565 + match node_type with 1566 + | "array" -> 1567 + let arr = jdec V3.array_meta_jsont json in 1568 + V3_node. 1569 + { kind = `Array arr; attrs = attrs_val; unknown = unknown_val } 1570 + | "group" -> 1571 + V3_node.{ kind = `Group; attrs = attrs_val; unknown = unknown_val } 1572 + | s -> 1573 + Jsont.Error.msgf Jsont.Meta.none "v3_jsont: unknown node_type: %s" s) 1389 1574 ~enc:(fun (t : V3_node.t) -> 1390 1575 let attrs_json = jenc attrs_jsont t.attrs in 1391 - let has_attrs = match attrs_json with 1392 - | Jsont.Object ([], _) -> false 1393 - | _ -> true 1576 + let has_attrs = 1577 + match attrs_json with Jsont.Object ([], _) -> false | _ -> true 1394 1578 in 1395 1579 match t.kind with 1396 1580 | `Array a -> 1397 - let arr_json = jenc V3.array_meta_jsont a in 1398 - let arr_mems = match arr_json with 1399 - | Jsont.Object (m, _) -> m 1400 - | _ -> [] 1401 - in 1402 - let mems = if has_attrs then 1403 - arr_mems @ [(("attributes", Jsont.Meta.none), attrs_json)] 1404 - else arr_mems 1405 - in 1406 - Jsont.Json.object' mems 1581 + let arr_json = jenc V3.array_meta_jsont a in 1582 + let arr_mems = 1583 + match arr_json with Jsont.Object (m, _) -> m | _ -> [] 1584 + in 1585 + let mems = 1586 + if has_attrs then 1587 + arr_mems @ [ (("attributes", Jsont.Meta.none), attrs_json) ] 1588 + else arr_mems 1589 + in 1590 + Jsont.Json.object' mems 1407 1591 | `Group -> 1408 - let mems = [ 1409 - (("zarr_format", Jsont.Meta.none), Jsont.Json.number 3.0); 1410 - (("node_type", Jsont.Meta.none), Jsont.Json.string "group"); 1411 - ] in 1412 - let mems = if has_attrs then 1413 - mems @ [(("attributes", Jsont.Meta.none), attrs_json)] 1414 - else mems 1415 - in 1416 - Jsont.Json.object' mems) 1592 + let mems = 1593 + [ 1594 + (("zarr_format", Jsont.Meta.none), Jsont.Json.number 3.0); 1595 + (("node_type", Jsont.Meta.none), Jsont.Json.string "group"); 1596 + ] 1597 + in 1598 + let mems = 1599 + if has_attrs then 1600 + mems @ [ (("attributes", Jsont.Meta.none), attrs_json) ] 1601 + else mems 1602 + in 1603 + Jsont.Json.object' mems) 1417 1604 Jsont.json 1418 1605 1419 1606 type t = [ `V2 of V2_node.t | `V3 of V3_node.t ] 1420 1607 1421 1608 let jsont : t Jsont.t = 1422 1609 let find_zarr_format mems = 1423 - List.find_map (fun ((n, _), v) -> 1424 - if n = "zarr_format" then 1425 - match v with 1426 - | Jsont.Number (f, _) -> Some (int_of_float f) 1427 - | _ -> None 1428 - else None) mems 1610 + List.find_map 1611 + (fun ((n, _), v) -> 1612 + if n = "zarr_format" then 1613 + match v with 1614 + | Jsont.Number (f, _) -> Some (int_of_float f) 1615 + | _ -> None 1616 + else None) 1617 + mems 1429 1618 in 1430 - let has_shape mems = 1431 - List.exists (fun ((k, _), _) -> k = "shape") mems 1432 - in 1619 + let has_shape mems = List.exists (fun ((k, _), _) -> k = "shape") mems in 1433 1620 Jsont.map ~kind:"Zarr" 1434 1621 ~dec:(fun json -> 1435 - let mems = match json with 1622 + let mems = 1623 + match json with 1436 1624 | Jsont.Object (m, _) -> m 1437 1625 | _ -> Jsont.Error.msgf Jsont.Meta.none "jsont: expected object" 1438 1626 in 1439 - let zarr_format = match find_zarr_format mems with 1627 + let zarr_format = 1628 + match find_zarr_format mems with 1440 1629 | Some n -> n 1441 1630 | None -> Jsont.Error.msgf Jsont.Meta.none "jsont: missing zarr_format" 1442 1631 in 1443 1632 match zarr_format with 1444 1633 | 2 -> 1445 - if has_shape mems then `V2 (jdec v2_array_jsont json) 1446 - else `V2 (jdec v2_group_jsont json) 1634 + if has_shape mems then `V2 (jdec v2_array_jsont json) 1635 + else `V2 (jdec v2_group_jsont json) 1447 1636 | 3 -> `V3 (jdec v3_jsont json) 1448 1637 | n -> Jsont.Error.msgf Jsont.Meta.none "jsont: unknown zarr_format: %d" n) 1449 1638 ~enc:(function 1450 - | `V2 node -> 1451 - (match V2_node.kind node with 1452 - | `Array _ -> jenc v2_array_jsont node 1453 - | `Group -> jenc v2_group_jsont node) 1639 + | `V2 node -> ( 1640 + match V2_node.kind node with 1641 + | `Array _ -> jenc v2_array_jsont node 1642 + | `Group -> jenc v2_group_jsont node) 1454 1643 | `V3 node -> jenc v3_jsont node) 1455 1644 Jsont.json 1456 1645 1457 1646 (* Consolidated metadata — V3 *) 1458 1647 1459 1648 module Consolidated = struct 1460 - type t = { 1461 - metadata : (string * V3_node.t) list; 1462 - kind : string; 1463 - } 1649 + type t = { metadata : (string * V3_node.t) list; kind : string } 1650 + 1464 1651 let metadata t = t.metadata 1465 1652 let kind t = t.kind 1466 1653 ··· 1468 1655 (* consolidated_metadata is an object with "metadata", "kind", "must_understand" *) 1469 1656 Jsont.map ~kind:"Consolidated" 1470 1657 ~dec:(fun json -> 1471 - let mems = match json with 1658 + let mems = 1659 + match json with 1472 1660 | Jsont.Object (mems, _) -> mems 1473 - | _ -> Jsont.Error.msgf Jsont.Meta.none "Consolidated: expected object" 1661 + | _ -> 1662 + Jsont.Error.msgf Jsont.Meta.none "Consolidated: expected object" 1474 1663 in 1475 - let find k = List.find_map (fun ((n, _), v) -> 1476 - if n = k then Some v else None) mems 1664 + let find k = 1665 + List.find_map (fun ((n, _), v) -> if n = k then Some v else None) mems 1477 1666 in 1478 - let kind = match find "kind" with 1479 - | Some (Jsont.String (s, _)) -> s | _ -> "inline" 1667 + let kind = 1668 + match find "kind" with 1669 + | Some (Jsont.String (s, _)) -> s 1670 + | _ -> "inline" 1480 1671 in 1481 - let metadata = match find "metadata" with 1672 + let metadata = 1673 + match find "metadata" with 1482 1674 | Some (Jsont.Object (entries, _)) -> 1483 - List.filter_map (fun ((path, _), node_json) -> 1484 - match Jsont.Json.decode v3_jsont node_json with 1485 - | Ok node -> Some (path, node) 1486 - | Error _ -> None) entries 1675 + List.filter_map 1676 + (fun ((path, _), node_json) -> 1677 + match Jsont.Json.decode v3_jsont node_json with 1678 + | Ok node -> Some (path, node) 1679 + | Error _ -> None) 1680 + entries 1487 1681 | _ -> [] 1488 1682 in 1489 1683 { metadata; kind }) 1490 1684 ~enc:(fun t -> 1491 - let entries = List.map (fun (path, node) -> 1492 - ((path, Jsont.Meta.none), jenc v3_jsont node)) t.metadata 1685 + let entries = 1686 + List.map 1687 + (fun (path, node) -> ((path, Jsont.Meta.none), jenc v3_jsont node)) 1688 + t.metadata 1493 1689 in 1494 - Jsont.Json.object' [ 1495 - (("metadata", Jsont.Meta.none), Jsont.Object (entries, Jsont.Meta.none)); 1496 - (("kind", Jsont.Meta.none), Jsont.Json.string t.kind); 1497 - (("must_understand", Jsont.Meta.none), Jsont.Json.bool false); 1498 - ]) 1690 + Jsont.Json.object' 1691 + [ 1692 + ( ("metadata", Jsont.Meta.none), 1693 + Jsont.Object (entries, Jsont.Meta.none) ); 1694 + (("kind", Jsont.Meta.none), Jsont.Json.string t.kind); 1695 + (("must_understand", Jsont.Meta.none), Jsont.Json.bool false); 1696 + ]) 1499 1697 Jsont.json 1500 1698 end 1501 1699 1502 1700 (* Consolidated metadata — V2 (.zmetadata) *) 1503 1701 1504 1702 module V2_consolidated = struct 1505 - type entry = { 1506 - path : string; 1507 - node : V2_node.t; 1508 - attrs : Attrs.t option; 1509 - } 1703 + type entry = { path : string; node : V2_node.t; attrs : Attrs.t option } 1704 + type t = { entries : entry list; format_version : int } 1510 1705 1511 - type t = { 1512 - entries : entry list; 1513 - format_version : int; 1514 - } 1515 1706 let entries t = t.entries 1516 1707 let format_version t = t.format_version 1517 1708 ··· 1519 1710 (* .zmetadata: {"metadata": {"path/.zarray": {...}, ...}, "zarr_consolidated_format": 1} *) 1520 1711 Jsont.map ~kind:"V2_consolidated" 1521 1712 ~dec:(fun json -> 1522 - let mems = match json with 1713 + let mems = 1714 + match json with 1523 1715 | Jsont.Object (mems, _) -> mems 1524 - | _ -> Jsont.Error.msgf Jsont.Meta.none "V2_consolidated: expected object" 1716 + | _ -> 1717 + Jsont.Error.msgf Jsont.Meta.none 1718 + "V2_consolidated: expected object" 1525 1719 in 1526 - let find k = List.find_map (fun ((n, _), v) -> 1527 - if n = k then Some v else None) mems 1720 + let find k = 1721 + List.find_map (fun ((n, _), v) -> if n = k then Some v else None) mems 1528 1722 in 1529 - let format_version = match find "zarr_consolidated_format" with 1530 - | Some (Jsont.Number (f, _)) -> int_of_float f | _ -> 1 1723 + let format_version = 1724 + match find "zarr_consolidated_format" with 1725 + | Some (Jsont.Number (f, _)) -> int_of_float f 1726 + | _ -> 1 1531 1727 in 1532 - let metadata = match find "metadata" with 1728 + let metadata = 1729 + match find "metadata" with 1533 1730 | Some (Jsont.Object (entries, _)) -> entries 1534 1731 | _ -> [] 1535 1732 in 1536 1733 (* Group entries by path prefix: collect .zarray/.zgroup and .zattrs *) 1537 1734 let tbl = Hashtbl.create 16 in 1538 - List.iter (fun ((key, _), value) -> 1539 - (* key is like "array1/.zarray" or "array1/.zattrs" or ".zgroup" *) 1540 - let parts = match String.rindex_opt key '/' with 1541 - | Some i -> (String.sub key 0 i, String.sub key (i + 1) (String.length key - i - 1)) 1542 - | None -> ("", key) 1543 - in 1544 - let (prefix, basename) = parts in 1545 - let (node_json, attrs_json) = 1546 - match Hashtbl.find_opt tbl prefix with 1547 - | Some v -> v | None -> (None, None) 1548 - in 1549 - let v = match basename with 1550 - | ".zarray" | ".zgroup" -> (Some value, attrs_json) 1551 - | ".zattrs" -> (node_json, Some value) 1552 - | _ -> (node_json, attrs_json) 1553 - in 1554 - Hashtbl.replace tbl prefix v 1555 - ) metadata; 1556 - let entries = Hashtbl.fold (fun path (node_json, attrs_json) acc -> 1557 - let node = match node_json with 1558 - | Some nj -> 1559 - (match Jsont.Json.decode v2_array_jsont nj with 1560 - | Ok n -> Some n 1561 - | Error _ -> 1562 - match Jsont.Json.decode v2_group_jsont nj with 1563 - | Ok n -> Some n | Error _ -> None) 1564 - | None -> None 1565 - in 1566 - let attrs = match attrs_json with 1567 - | Some aj -> 1568 - (match Jsont.Json.decode attrs_jsont aj with 1569 - | Ok a -> Some a | Error _ -> None) 1570 - | None -> None 1571 - in 1572 - match node with 1573 - | Some n -> { path; node = n; attrs } :: acc 1574 - | None -> acc 1575 - ) tbl [] in 1576 - let entries = List.sort (fun a b -> String.compare a.path b.path) entries in 1735 + List.iter 1736 + (fun ((key, _), value) -> 1737 + (* key is like "array1/.zarray" or "array1/.zattrs" or ".zgroup" *) 1738 + let parts = 1739 + match String.rindex_opt key '/' with 1740 + | Some i -> 1741 + ( String.sub key 0 i, 1742 + String.sub key (i + 1) (String.length key - i - 1) ) 1743 + | None -> ("", key) 1744 + in 1745 + let prefix, basename = parts in 1746 + let node_json, attrs_json = 1747 + match Hashtbl.find_opt tbl prefix with 1748 + | Some v -> v 1749 + | None -> (None, None) 1750 + in 1751 + let v = 1752 + match basename with 1753 + | ".zarray" | ".zgroup" -> (Some value, attrs_json) 1754 + | ".zattrs" -> (node_json, Some value) 1755 + | _ -> (node_json, attrs_json) 1756 + in 1757 + Hashtbl.replace tbl prefix v) 1758 + metadata; 1759 + let entries = 1760 + Hashtbl.fold 1761 + (fun path (node_json, attrs_json) acc -> 1762 + let node = 1763 + match node_json with 1764 + | Some nj -> ( 1765 + match Jsont.Json.decode v2_array_jsont nj with 1766 + | Ok n -> Some n 1767 + | Error _ -> ( 1768 + match Jsont.Json.decode v2_group_jsont nj with 1769 + | Ok n -> Some n 1770 + | Error _ -> None)) 1771 + | None -> None 1772 + in 1773 + let attrs = 1774 + match attrs_json with 1775 + | Some aj -> ( 1776 + match Jsont.Json.decode attrs_jsont aj with 1777 + | Ok a -> Some a 1778 + | Error _ -> None) 1779 + | None -> None 1780 + in 1781 + match node with 1782 + | Some n -> { path; node = n; attrs } :: acc 1783 + | None -> acc) 1784 + tbl [] 1785 + in 1786 + let entries = 1787 + List.sort (fun a b -> String.compare a.path b.path) entries 1788 + in 1577 1789 { entries; format_version }) 1578 1790 ~enc:(fun t -> 1579 - let metadata_entries = List.concat_map (fun entry -> 1580 - let prefix = if entry.path = "" then "" else entry.path ^ "/" in 1581 - let node_entries = match V2_node.kind entry.node with 1582 - | `Array a -> 1583 - (match Jsont.Json.encode V2.array_meta_jsont a with 1584 - | Ok j -> [((prefix ^ ".zarray", Jsont.Meta.none), j)] 1585 - | Error _ -> []) 1586 - | `Group -> 1587 - [((prefix ^ ".zgroup", Jsont.Meta.none), 1588 - Jsont.Json.object' [(("zarr_format", Jsont.Meta.none), Jsont.Json.number 2.0)])] 1589 - in 1590 - let attrs_entries = match entry.attrs with 1591 - | Some a -> 1592 - (match Jsont.Json.encode attrs_jsont a with 1593 - | Ok j -> [((prefix ^ ".zattrs", Jsont.Meta.none), j)] 1594 - | Error _ -> []) 1595 - | None -> [] 1596 - in 1597 - node_entries @ attrs_entries 1598 - ) t.entries in 1599 - Jsont.Json.object' [ 1600 - (("metadata", Jsont.Meta.none), Jsont.Object (metadata_entries, Jsont.Meta.none)); 1601 - (("zarr_consolidated_format", Jsont.Meta.none), Jsont.Json.number (float_of_int t.format_version)); 1602 - ]) 1791 + let metadata_entries = 1792 + List.concat_map 1793 + (fun entry -> 1794 + let prefix = if entry.path = "" then "" else entry.path ^ "/" in 1795 + let node_entries = 1796 + match V2_node.kind entry.node with 1797 + | `Array a -> ( 1798 + match Jsont.Json.encode V2.array_meta_jsont a with 1799 + | Ok j -> [ ((prefix ^ ".zarray", Jsont.Meta.none), j) ] 1800 + | Error _ -> []) 1801 + | `Group -> 1802 + [ 1803 + ( (prefix ^ ".zgroup", Jsont.Meta.none), 1804 + Jsont.Json.object' 1805 + [ 1806 + ( ("zarr_format", Jsont.Meta.none), 1807 + Jsont.Json.number 2.0 ); 1808 + ] ); 1809 + ] 1810 + in 1811 + let attrs_entries = 1812 + match entry.attrs with 1813 + | Some a -> ( 1814 + match Jsont.Json.encode attrs_jsont a with 1815 + | Ok j -> [ ((prefix ^ ".zattrs", Jsont.Meta.none), j) ] 1816 + | Error _ -> []) 1817 + | None -> [] 1818 + in 1819 + node_entries @ attrs_entries) 1820 + t.entries 1821 + in 1822 + Jsont.Json.object' 1823 + [ 1824 + ( ("metadata", Jsont.Meta.none), 1825 + Jsont.Object (metadata_entries, Jsont.Meta.none) ); 1826 + ( ("zarr_consolidated_format", Jsont.Meta.none), 1827 + Jsont.Json.number (float_of_int t.format_version) ); 1828 + ]) 1603 1829 Jsont.json 1604 1830 end 1605 1831 ··· 1612 1838 children : (string * probe_result) list; 1613 1839 } 1614 1840 1615 - let decode_string codec s = 1616 - Jsont_bytesrw.decode_string codec s 1841 + let decode_string codec s = Jsont_bytesrw.decode_string codec s 1617 1842 1618 1843 let try_v3_consolidated contents = 1619 1844 match Jsont_bytesrw.decode_string Jsont.json contents with 1620 1845 | Ok (Jsont.Object (mems, _)) -> 1621 - List.find_map (fun ((k, _), v) -> 1622 - if k = "consolidated_metadata" then 1623 - match Jsont.Json.decode Consolidated.jsont v with 1624 - | Ok c -> Some c | Error _ -> None 1625 - else None) mems 1846 + List.find_map 1847 + (fun ((k, _), v) -> 1848 + if k = "consolidated_metadata" then 1849 + match Jsont.Json.decode Consolidated.jsont v with 1850 + | Ok c -> Some c 1851 + | Error _ -> None 1852 + else None) 1853 + mems 1626 1854 | _ -> None 1627 1855 1628 1856 (* Build children tree from consolidated metadata *) 1629 1857 let rec children_of_v3_consolidated (c : Consolidated.t) = 1630 1858 let immediate = Hashtbl.create 16 in 1631 - List.iter (fun (path, node) -> 1632 - let top, rest = match String.index_opt path '/' with 1633 - | Some i -> 1634 - String.sub path 0 i, 1635 - Some (String.sub path (i + 1) (String.length path - i - 1), node) 1636 - | None -> path, None 1637 - in 1638 - let (direct, nested) = match Hashtbl.find_opt immediate top with 1639 - | Some v -> v | None -> (None, []) 1640 - in 1641 - match rest with 1642 - | None -> Hashtbl.replace immediate top (Some node, nested) 1643 - | Some sub -> Hashtbl.replace immediate top (direct, sub :: nested) 1644 - ) (Consolidated.metadata c); 1645 - Hashtbl.fold (fun name (direct, nested) acc -> 1646 - let node = match direct with 1647 - | Some n -> n 1648 - | None -> 1649 - V3_node.{ kind = `Group; attrs = Attrs.empty; 1650 - unknown = Jsont.Json.object' [] } 1651 - in 1652 - let children = match V3_node.kind node, nested with 1653 - | `Group, _ :: _ -> 1654 - let sub_c = { Consolidated.metadata = List.rev nested; 1655 - kind = c.kind } in 1656 - children_of_v3_consolidated sub_c 1657 - | _ -> [] 1658 - in 1659 - (name, { node = `V3 node; attrs = None; 1660 - consolidated = None; children }) :: acc 1661 - ) immediate [] 1859 + List.iter 1860 + (fun (path, node) -> 1861 + let top, rest = 1862 + match String.index_opt path '/' with 1863 + | Some i -> 1864 + ( String.sub path 0 i, 1865 + Some (String.sub path (i + 1) (String.length path - i - 1), node) 1866 + ) 1867 + | None -> (path, None) 1868 + in 1869 + let direct, nested = 1870 + match Hashtbl.find_opt immediate top with 1871 + | Some v -> v 1872 + | None -> (None, []) 1873 + in 1874 + match rest with 1875 + | None -> Hashtbl.replace immediate top (Some node, nested) 1876 + | Some sub -> Hashtbl.replace immediate top (direct, sub :: nested)) 1877 + (Consolidated.metadata c); 1878 + Hashtbl.fold 1879 + (fun name (direct, nested) acc -> 1880 + let node = 1881 + match direct with 1882 + | Some n -> n 1883 + | None -> 1884 + V3_node. 1885 + { 1886 + kind = `Group; 1887 + attrs = Attrs.empty; 1888 + unknown = Jsont.Json.object' []; 1889 + } 1890 + in 1891 + let children = 1892 + match (V3_node.kind node, nested) with 1893 + | `Group, _ :: _ -> 1894 + let sub_c = 1895 + { Consolidated.metadata = List.rev nested; kind = c.kind } 1896 + in 1897 + children_of_v3_consolidated sub_c 1898 + | _ -> [] 1899 + in 1900 + (name, { node = `V3 node; attrs = None; consolidated = None; children }) 1901 + :: acc) 1902 + immediate [] 1662 1903 |> List.sort (fun (a, _) (b, _) -> String.compare a b) 1663 1904 1664 1905 and children_of_v2_consolidated (c : V2_consolidated.t) = 1665 1906 (* Build tree: group entries by top-level path component *) 1666 1907 let immediate = Hashtbl.create 16 in 1667 - List.iter (fun ({ V2_consolidated.path; _ } as entry) -> 1668 - if path <> "" then begin 1669 - let top, is_direct = match String.index_opt path '/' with 1670 - | Some i -> String.sub path 0 i, false 1671 - | None -> path, true 1908 + List.iter 1909 + (fun ({ V2_consolidated.path; _ } as entry) -> 1910 + if path <> "" then begin 1911 + let top, is_direct = 1912 + match String.index_opt path '/' with 1913 + | Some i -> (String.sub path 0 i, false) 1914 + | None -> (path, true) 1915 + in 1916 + let direct, nested = 1917 + match Hashtbl.find_opt immediate top with 1918 + | Some v -> v 1919 + | None -> (None, []) 1920 + in 1921 + if is_direct then Hashtbl.replace immediate top (Some entry, nested) 1922 + else 1923 + let rest_path = 1924 + match String.index_opt path '/' with 1925 + | Some i -> String.sub path (i + 1) (String.length path - i - 1) 1926 + | None -> path 1927 + in 1928 + Hashtbl.replace immediate top 1929 + (direct, { entry with path = rest_path } :: nested) 1930 + end) 1931 + (V2_consolidated.entries c); 1932 + Hashtbl.fold 1933 + (fun name (direct, nested) acc -> 1934 + let node, attrs = 1935 + match direct with 1936 + | Some e -> (e.V2_consolidated.node, e.V2_consolidated.attrs) 1937 + | None -> 1938 + ( V2_node. 1939 + { 1940 + kind = `Group; 1941 + attrs = Attrs.empty; 1942 + unknown = Jsont.Json.object' []; 1943 + }, 1944 + None ) 1672 1945 in 1673 - let (direct, nested) = match Hashtbl.find_opt immediate top with 1674 - | Some v -> v | None -> (None, []) 1946 + let children = 1947 + match nested with 1948 + | [] -> [] 1949 + | _ -> 1950 + let sub_c = 1951 + { 1952 + V2_consolidated.entries = List.rev nested; 1953 + format_version = V2_consolidated.format_version c; 1954 + } 1955 + in 1956 + children_of_v2_consolidated sub_c 1675 1957 in 1676 - if is_direct then 1677 - Hashtbl.replace immediate top (Some entry, nested) 1678 - else 1679 - let rest_path = match String.index_opt path '/' with 1680 - | Some i -> String.sub path (i + 1) (String.length path - i - 1) 1681 - | None -> path 1682 - in 1683 - Hashtbl.replace immediate top 1684 - (direct, { entry with path = rest_path } :: nested) 1685 - end 1686 - ) (V2_consolidated.entries c); 1687 - Hashtbl.fold (fun name (direct, nested) acc -> 1688 - let node, attrs = match direct with 1689 - | Some e -> e.V2_consolidated.node, e.V2_consolidated.attrs 1690 - | None -> 1691 - V2_node.{ kind = `Group; attrs = Attrs.empty; 1692 - unknown = Jsont.Json.object' [] }, None 1693 - in 1694 - let children = match nested with 1695 - | [] -> [] 1696 - | _ -> 1697 - let sub_c = { V2_consolidated.entries = List.rev nested; 1698 - format_version = V2_consolidated.format_version c } in 1699 - children_of_v2_consolidated sub_c 1700 - in 1701 - (name, { node = `V2 node; attrs; 1702 - consolidated = None; children }) :: acc 1703 - ) immediate [] 1958 + (name, { node = `V2 node; attrs; consolidated = None; children }) :: acc) 1959 + immediate [] 1704 1960 |> List.sort (fun (a, _) (b, _) -> String.compare a b) 1705 1961 1706 1962 let read_v2_attrs read_rel = 1707 1963 match read_rel ".zattrs" with 1708 - | Ok a -> (match decode_string attrs_jsont a with Ok a -> Some a | Error _ -> None) 1964 + | Ok a -> ( 1965 + match decode_string attrs_jsont a with Ok a -> Some a | Error _ -> None) 1709 1966 | Error _ -> None 1710 1967 1711 1968 let probe ~read path = 1712 1969 let read_rel = read in 1713 1970 (* Try v3 first *) 1714 1971 match read_rel "zarr.json" with 1715 - | Ok contents -> 1716 - (match decode_string v3_jsont contents with 1717 - | Ok node -> 1718 - let consolidated = Option.map (fun c -> `V3 c) 1719 - (try_v3_consolidated contents) in 1720 - let children = match consolidated with 1721 - | Some (`V3 c) -> children_of_v3_consolidated c 1722 - | _ -> [] 1723 - in 1724 - Ok { node = `V3 node; attrs = None; consolidated; children } 1725 - | Error e -> Error (Printf.sprintf "zarr.json: %s" e)) 1726 - | Error _ -> 1727 - match read_rel ".zarray" with 1728 - | Ok contents -> 1729 - (match decode_string v2_array_jsont contents with 1730 - | Ok node -> 1731 - let attrs = read_v2_attrs read_rel in 1732 - Ok { node = `V2 node; attrs; consolidated = None; children = [] } 1733 - | Error e -> Error (Printf.sprintf ".zarray: %s" e)) 1734 - | Error _ -> 1735 - match read_rel ".zgroup" with 1736 - | Ok contents -> 1737 - (match decode_string v2_group_jsont contents with 1738 - | Ok node -> 1739 - let attrs = read_v2_attrs read_rel in 1740 - let consolidated = match read_rel ".zmetadata" with 1741 - | Ok mc -> 1742 - (match decode_string V2_consolidated.jsont mc with 1743 - | Ok c -> Some (`V2 c) | Error _ -> None) 1744 - | Error _ -> None 1745 - in 1746 - let children = match consolidated with 1747 - | Some (`V2 c) -> children_of_v2_consolidated c 1748 - | _ -> [] 1749 - in 1750 - Ok { node = `V2 node; attrs; consolidated; children } 1751 - | Error e -> Error (Printf.sprintf ".zgroup: %s" e)) 1752 - | Error _ -> 1753 - match read_rel ".zmetadata" with 1754 - | Ok mc -> 1755 - (match decode_string V2_consolidated.jsont mc with 1756 - | Ok c -> 1757 - let node = V2_node.{ kind = `Group; attrs = Attrs.empty; 1758 - unknown = Jsont.Json.object' [] } in 1759 - let attrs = read_v2_attrs read_rel in 1760 - let children = children_of_v2_consolidated c in 1761 - Ok { node = `V2 node; attrs; consolidated = Some (`V2 c); children } 1762 - | Error e -> Error (Printf.sprintf ".zmetadata: %s" e)) 1763 - | Error _ -> 1764 - Error (Printf.sprintf 1765 - "%s: no zarr metadata found (tried zarr.json, .zarray, .zgroup, .zmetadata)" 1766 - path) 1972 + | Ok contents -> ( 1973 + match decode_string v3_jsont contents with 1974 + | Ok node -> 1975 + let consolidated = 1976 + Option.map (fun c -> `V3 c) (try_v3_consolidated contents) 1977 + in 1978 + let children = 1979 + match consolidated with 1980 + | Some (`V3 c) -> children_of_v3_consolidated c 1981 + | _ -> [] 1982 + in 1983 + Ok { node = `V3 node; attrs = None; consolidated; children } 1984 + | Error e -> Error (Printf.sprintf "zarr.json: %s" e)) 1985 + | Error _ -> ( 1986 + match read_rel ".zarray" with 1987 + | Ok contents -> ( 1988 + match decode_string v2_array_jsont contents with 1989 + | Ok node -> 1990 + let attrs = read_v2_attrs read_rel in 1991 + Ok { node = `V2 node; attrs; consolidated = None; children = [] } 1992 + | Error e -> Error (Printf.sprintf ".zarray: %s" e)) 1993 + | Error _ -> ( 1994 + match read_rel ".zgroup" with 1995 + | Ok contents -> ( 1996 + match decode_string v2_group_jsont contents with 1997 + | Ok node -> 1998 + let attrs = read_v2_attrs read_rel in 1999 + let consolidated = 2000 + match read_rel ".zmetadata" with 2001 + | Ok mc -> ( 2002 + match decode_string V2_consolidated.jsont mc with 2003 + | Ok c -> Some (`V2 c) 2004 + | Error _ -> None) 2005 + | Error _ -> None 2006 + in 2007 + let children = 2008 + match consolidated with 2009 + | Some (`V2 c) -> children_of_v2_consolidated c 2010 + | _ -> [] 2011 + in 2012 + Ok { node = `V2 node; attrs; consolidated; children } 2013 + | Error e -> Error (Printf.sprintf ".zgroup: %s" e)) 2014 + | Error _ -> ( 2015 + match read_rel ".zmetadata" with 2016 + | Ok mc -> ( 2017 + match decode_string V2_consolidated.jsont mc with 2018 + | Ok c -> 2019 + let node = 2020 + V2_node. 2021 + { 2022 + kind = `Group; 2023 + attrs = Attrs.empty; 2024 + unknown = Jsont.Json.object' []; 2025 + } 2026 + in 2027 + let attrs = read_v2_attrs read_rel in 2028 + let children = children_of_v2_consolidated c in 2029 + Ok 2030 + { 2031 + node = `V2 node; 2032 + attrs; 2033 + consolidated = Some (`V2 c); 2034 + children; 2035 + } 2036 + | Error e -> Error (Printf.sprintf ".zmetadata: %s" e)) 2037 + | Error _ -> 2038 + Error 2039 + (Printf.sprintf 2040 + "%s: no zarr metadata found (tried zarr.json, .zarray, \ 2041 + .zgroup, .zmetadata)" 2042 + path)))) 1767 2043 1768 2044 (* Pretty-printing *) 1769 2045 ··· 1783 2059 | `Structured _ -> pf ppf "structured" 1784 2060 1785 2061 let pp_data_type ppf = function 1786 - | `Bool -> pf ppf "bool" | `Int8 -> pf ppf "int8" 1787 - | `Int16 -> pf ppf "int16" | `Int32 -> pf ppf "int32" 1788 - | `Int64 -> pf ppf "int64" | `Uint8 -> pf ppf "uint8" 1789 - | `Uint16 -> pf ppf "uint16" | `Uint32 -> pf ppf "uint32" 1790 - | `Uint64 -> pf ppf "uint64" | `Float16 -> pf ppf "float16" 1791 - | `Float32 -> pf ppf "float32" | `Float64 -> pf ppf "float64" 1792 - | `Complex64 -> pf ppf "complex64" | `Complex128 -> pf ppf "complex128" 2062 + | `Bool -> pf ppf "bool" 2063 + | `Int8 -> pf ppf "int8" 2064 + | `Int16 -> pf ppf "int16" 2065 + | `Int32 -> pf ppf "int32" 2066 + | `Int64 -> pf ppf "int64" 2067 + | `Uint8 -> pf ppf "uint8" 2068 + | `Uint16 -> pf ppf "uint16" 2069 + | `Uint32 -> pf ppf "uint32" 2070 + | `Uint64 -> pf ppf "uint64" 2071 + | `Float16 -> pf ppf "float16" 2072 + | `Float32 -> pf ppf "float32" 2073 + | `Float64 -> pf ppf "float64" 2074 + | `Complex64 -> pf ppf "complex64" 2075 + | `Complex128 -> pf ppf "complex128" 1793 2076 | `Raw n -> pf ppf "r%d" n 1794 2077 | `Other o -> pf ppf "%s" (Other_ext.name o) 1795 2078 ··· 1802 2085 | `Bytes s -> pf ppf "<%d bytes>" (String.length s) 1803 2086 1804 2087 let pp_shape ppf shape = 1805 - Format.pp_print_list ~pp_sep:(fun ppf () -> pf ppf "x") 2088 + Format.pp_print_list 2089 + ~pp_sep:(fun ppf () -> pf ppf "x") 1806 2090 Format.pp_print_int ppf shape 1807 2091 1808 2092 let pp_floats ppf fs = 1809 - Format.pp_print_list ~pp_sep:(fun ppf () -> pf ppf ",") 1810 - (fun ppf f -> pf ppf "%.4g" f) ppf fs 1811 - 1812 - let pp_opt pp ppf = function 1813 - | Some v -> pp ppf v 1814 - | None -> () 1815 - 1816 - let pp_labelled label pp ppf v = 1817 - pf ppf " %s=[%a]" label pp v 2093 + Format.pp_print_list 2094 + ~pp_sep:(fun ppf () -> pf ppf ",") 2095 + (fun ppf f -> pf ppf "%.4g" f) 2096 + ppf fs 1818 2097 1819 - let node_attrs = function 1820 - | `V2 n -> V2_node.attrs n 1821 - | `V3 n -> V3_node.attrs n 2098 + let pp_opt pp ppf = function Some v -> pp ppf v | None -> () 2099 + let pp_labelled label pp ppf v = pf ppf " %s=[%a]" label pp v 2100 + let node_attrs = function `V2 n -> V2_node.attrs n | `V3 n -> V3_node.attrs n 1822 2101 1823 2102 let pp_node_kind ppf = function 1824 - | `V2 n -> 1825 - (match V2_node.kind n with 1826 - | `Array a -> pf ppf "array %a %a" pp_dtype (V2.Array_meta.dtype a) pp_shape (V2.Array_meta.shape a) 1827 - | `Group -> pf ppf "group") 1828 - | `V3 n -> 1829 - (match V3_node.kind n with 1830 - | `Array a -> pf ppf "array %a %a" pp_data_type (V3.Array_meta.data_type a) pp_shape (V3.Array_meta.shape a) 1831 - | `Group -> pf ppf "group") 2103 + | `V2 n -> ( 2104 + match V2_node.kind n with 2105 + | `Array a -> 2106 + pf ppf "array %a %a" pp_dtype (V2.Array_meta.dtype a) pp_shape 2107 + (V2.Array_meta.shape a) 2108 + | `Group -> pf ppf "group") 2109 + | `V3 n -> ( 2110 + match V3_node.kind n with 2111 + | `Array a -> 2112 + pf ppf "array %a %a" pp_data_type 2113 + (V3.Array_meta.data_type a) 2114 + pp_shape (V3.Array_meta.shape a) 2115 + | `Group -> pf ppf "group") 1832 2116 1833 2117 let rec pp_tree indent ppf children = 1834 - List.iter (fun (name, (result : probe_result)) -> 1835 - pf ppf "\n%s%s [%a]" indent name pp_node_kind result.node; 1836 - let attrs = match result.attrs with 1837 - | Some a -> a | None -> node_attrs result.node 1838 - in 1839 - pp_indented_attrs (indent ^ " ") ppf attrs; 1840 - if result.children <> [] then 1841 - pp_tree (indent ^ " ") ppf result.children 1842 - ) children 2118 + List.iter 2119 + (fun (name, (result : probe_result)) -> 2120 + pf ppf "\n%s%s [%a]" indent name pp_node_kind result.node; 2121 + let attrs = 2122 + match result.attrs with Some a -> a | None -> node_attrs result.node 2123 + in 2124 + pp_indented_attrs (indent ^ " ") ppf attrs; 2125 + if result.children <> [] then pp_tree (indent ^ " ") ppf result.children) 2126 + children 1843 2127 1844 2128 and pp_indented_attrs indent ppf attrs = 1845 2129 let nl () = pf ppf "\n%s" indent in 1846 2130 (match Attrs.proj attrs with 1847 - | Some p -> 1848 - nl (); pf ppf "proj:"; 1849 - Option.iter (pf ppf " code=%s") (Conv.Proj.code p); 1850 - Option.iter (fun _ -> pf ppf " wkt2=...") (Conv.Proj.wkt2 p); 1851 - Option.iter (fun _ -> pf ppf " projjson=...") (Conv.Proj.projjson p) 1852 - | None -> ()); 2131 + | Some p -> 2132 + nl (); 2133 + pf ppf "proj:"; 2134 + Option.iter (pf ppf " code=%s") (Conv.Proj.code p); 2135 + Option.iter (fun _ -> pf ppf " wkt2=...") (Conv.Proj.wkt2 p); 2136 + Option.iter (fun _ -> pf ppf " projjson=...") (Conv.Proj.projjson p) 2137 + | None -> ()); 1853 2138 (match Attrs.spatial attrs with 1854 - | Some s -> 1855 - nl (); pf ppf "spatial: dims=[%a]" 1856 - (Format.pp_print_list ~pp_sep:(fun ppf () -> pf ppf ",") 1857 - Format.pp_print_string) (Conv.Spatial.dimensions s); 1858 - pp_opt (pp_labelled "bbox" pp_floats) ppf (Conv.Spatial.bbox s); 1859 - pp_opt (pp_labelled "transform" pp_floats) ppf (Conv.Spatial.transform s); 1860 - pp_opt (pp_labelled "shape" pp_shape) ppf (Conv.Spatial.shape s); 1861 - (match Conv.Spatial.registration s with 1862 - | Some `Pixel -> pf ppf " reg=pixel" | Some `Node -> pf ppf " reg=node" 2139 + | Some s -> ( 2140 + nl (); 2141 + pf ppf "spatial: dims=[%a]" 2142 + (Format.pp_print_list 2143 + ~pp_sep:(fun ppf () -> pf ppf ",") 2144 + Format.pp_print_string) 2145 + (Conv.Spatial.dimensions s); 2146 + pp_opt (pp_labelled "bbox" pp_floats) ppf (Conv.Spatial.bbox s); 2147 + pp_opt (pp_labelled "transform" pp_floats) ppf (Conv.Spatial.transform s); 2148 + pp_opt (pp_labelled "shape" pp_shape) ppf (Conv.Spatial.shape s); 2149 + match Conv.Spatial.registration s with 2150 + | Some `Pixel -> pf ppf " reg=pixel" 2151 + | Some `Node -> pf ppf " reg=node" 1863 2152 | None -> ()) 1864 - | None -> ()); 2153 + | None -> ()); 1865 2154 (match Attrs.multiscales attrs with 1866 - | Some m -> 1867 - let layout = Conv.Multiscales.layout m in 1868 - nl (); pf ppf "multiscales: %d levels" (List.length layout); 1869 - Option.iter (pf ppf " resampling=%s") (Conv.Multiscales.resampling_method m); 1870 - List.iter (fun item -> 1871 - pf ppf "\n%s %s" indent (Conv.Multiscales.Layout_item.asset item); 1872 - Option.iter (pf ppf " <- %s") (Conv.Multiscales.Layout_item.derived_from item); 1873 - Option.iter (fun t -> 1874 - pp_opt (pp_labelled "scale" pp_floats) ppf (Conv.Multiscales.Transform.scale t) 1875 - ) (Conv.Multiscales.Layout_item.transform item) 1876 - ) layout 1877 - | None -> ()); 2155 + | Some m -> 2156 + let layout = Conv.Multiscales.layout m in 2157 + nl (); 2158 + pf ppf "multiscales: %d levels" (List.length layout); 2159 + Option.iter (pf ppf " resampling=%s") 2160 + (Conv.Multiscales.resampling_method m); 2161 + List.iter 2162 + (fun item -> 2163 + pf ppf "\n%s %s" indent (Conv.Multiscales.Layout_item.asset item); 2164 + Option.iter (pf ppf " <- %s") 2165 + (Conv.Multiscales.Layout_item.derived_from item); 2166 + Option.iter 2167 + (fun t -> 2168 + pp_opt 2169 + (pp_labelled "scale" pp_floats) 2170 + ppf 2171 + (Conv.Multiscales.Transform.scale t)) 2172 + (Conv.Multiscales.Layout_item.transform item)) 2173 + layout 2174 + | None -> ()); 1878 2175 (* geoemb *) 1879 2176 (match Attrs.geoemb attrs with 1880 - | Some g -> 1881 - let ty = match Conv.Geoemb.type_ g with `Pixel -> "pixel" | `Chip -> "chip" in 1882 - nl (); pf ppf "geoemb: %s %dd model=%s dtype=%s" 1883 - ty (Conv.Geoemb.dimensions g) (Conv.Geoemb.model g) (Conv.Geoemb.data_type g); 1884 - Option.iter (pf ppf " gsd=%.4g") (Conv.Geoemb.gsd g); 1885 - Option.iter (pf ppf " layout=%s") (Conv.Geoemb.spatial_layout g); 1886 - Option.iter (pf ppf " build=%s") (Conv.Geoemb.build_version g); 1887 - (match Conv.Geoemb.chip_layout g with 2177 + | Some g -> ( 2178 + let ty = 2179 + match Conv.Geoemb.type_ g with `Pixel -> "pixel" | `Chip -> "chip" 2180 + in 2181 + nl (); 2182 + pf ppf "geoemb: %s %dd model=%s dtype=%s" ty (Conv.Geoemb.dimensions g) 2183 + (Conv.Geoemb.model g) (Conv.Geoemb.data_type g); 2184 + Option.iter (pf ppf " gsd=%.4g") (Conv.Geoemb.gsd g); 2185 + Option.iter (pf ppf " layout=%s") (Conv.Geoemb.spatial_layout g); 2186 + Option.iter (pf ppf " build=%s") (Conv.Geoemb.build_version g); 2187 + (match Conv.Geoemb.chip_layout g with 1888 2188 | Some cl -> 1889 - let lt = match Conv.Geoemb.Chip_layout.layout_type cl with 1890 - | `Regular_grid -> "regular_grid" | `Irregular -> "irregular" in 1891 - let (h, w) = Conv.Geoemb.Chip_layout.chip_size cl in 1892 - nl (); pf ppf " chip: %s %dx%d" lt h w; 1893 - Option.iter (fun (sy, sx) -> pf ppf " stride=%dx%d" sy sx) 1894 - (Conv.Geoemb.Chip_layout.stride cl) 2189 + let lt = 2190 + match Conv.Geoemb.Chip_layout.layout_type cl with 2191 + | `Regular_grid -> "regular_grid" 2192 + | `Irregular -> "irregular" 2193 + in 2194 + let h, w = Conv.Geoemb.Chip_layout.chip_size cl in 2195 + nl (); 2196 + pf ppf " chip: %s %dx%d" lt h w; 2197 + Option.iter 2198 + (fun (sy, sx) -> pf ppf " stride=%dx%d" sy sx) 2199 + (Conv.Geoemb.Chip_layout.stride cl) 1895 2200 | None -> ()); 1896 - (match Conv.Geoemb.quantization g with 1897 - | Some q -> 1898 - nl (); pf ppf " quantization: %s %s" (Conv.Geoemb.Quantization.meth q) 1899 - (Conv.Geoemb.Quantization.original_dtype q); 1900 - Option.iter (pf ppf " -> %s") (Conv.Geoemb.Quantization.quantized_dtype q); 1901 - (match Conv.Geoemb.Quantization.scale q with 1902 - | Some (`Scalar s) -> 1903 - pf ppf " scale=%g" (Conv.Geoemb.Scale.Scalar.scale s); 1904 - if Conv.Geoemb.Scale.Scalar.offset s <> 0.0 then 1905 - pf ppf " offset=%g" (Conv.Geoemb.Scale.Scalar.offset s) 1906 - | Some (`Array a) -> 1907 - pf ppf " scale_array=%s" (Conv.Geoemb.Scale.Array_.array_name a); 1908 - Option.iter (pf ppf " nodata=%s") (Conv.Geoemb.Scale.Array_.nodata a) 1909 - | None -> ()) 2201 + match Conv.Geoemb.quantization g with 2202 + | Some q -> ( 2203 + nl (); 2204 + pf ppf " quantization: %s %s" 2205 + (Conv.Geoemb.Quantization.meth q) 2206 + (Conv.Geoemb.Quantization.original_dtype q); 2207 + Option.iter (pf ppf " -> %s") 2208 + (Conv.Geoemb.Quantization.quantized_dtype q); 2209 + match Conv.Geoemb.Quantization.scale q with 2210 + | Some (`Scalar s) -> 2211 + pf ppf " scale=%g" (Conv.Geoemb.Scale.Scalar.scale s); 2212 + if Conv.Geoemb.Scale.Scalar.offset s <> 0.0 then 2213 + pf ppf " offset=%g" (Conv.Geoemb.Scale.Scalar.offset s) 2214 + | Some (`Array a) -> 2215 + pf ppf " scale_array=%s" (Conv.Geoemb.Scale.Array_.array_name a); 2216 + Option.iter (pf ppf " nodata=%s") 2217 + (Conv.Geoemb.Scale.Array_.nodata a) 2218 + | None -> ()) 1910 2219 | None -> ()) 1911 - | None -> ()); 1912 - (match Attrs.unknown attrs with 1913 - | Jsont.Object (mems, _) -> 1914 - List.iter (fun ((k, _), v) -> 1915 - let vs = match Jsont_bytesrw.encode_string ~format:Jsont.Minify Jsont.json v with 1916 - | Ok s when String.length s > 60 -> String.sub s 0 57 ^ "..." 1917 - | Ok s -> s | Error _ -> "?" 1918 - in 1919 - nl (); pf ppf "%s: %s" k vs 1920 - ) mems 1921 - | _ -> ()) 2220 + | None -> ()); 2221 + match Attrs.unknown attrs with 2222 + | Jsont.Object (mems, _) -> 2223 + List.iter 2224 + (fun ((k, _), v) -> 2225 + let vs = 2226 + match 2227 + Jsont_bytesrw.encode_string ~format:Jsont.Minify Jsont.json v 2228 + with 2229 + | Ok s when String.length s > 60 -> String.sub s 0 57 ^ "..." 2230 + | Ok s -> s 2231 + | Error _ -> "?" 2232 + in 2233 + nl (); 2234 + pf ppf "%s: %s" k vs) 2235 + mems 2236 + | _ -> () 1922 2237 1923 2238 let pp_attrs ppf attrs = pp_indented_attrs " " ppf attrs 1924 2239 1925 2240 let pp_probe_result ppf result = 1926 2241 pf ppf "[%a]" pp_node_kind result.node; 1927 - let attrs = match result.attrs with 1928 - | Some a -> a | None -> node_attrs result.node 2242 + let attrs = 2243 + match result.attrs with Some a -> a | None -> node_attrs result.node 1929 2244 in 1930 2245 pp_indented_attrs " " ppf attrs; 1931 - if result.children <> [] then 1932 - pp_tree " " ppf result.children; 2246 + if result.children <> [] then pp_tree " " ppf result.children; 1933 2247 pf ppf "\n"
+307 -316
src/zarr_jsont.mli
··· 1 1 (** Type-safe bidirectional JSON codecs for 2 - {{:https://zarr-specs.readthedocs.io/en/latest/}Zarr} v2 and v3 3 - array and group metadata. 2 + {{:https://zarr-specs.readthedocs.io/en/latest/}Zarr} v2 and v3 array and 3 + group metadata. 4 4 5 - This library provides {!Jsont.t} codecs for decoding and encoding the 6 - JSON metadata used by 7 - {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html}Zarr v2} 8 - and {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html}Zarr v3} 9 - stores. It also includes best-effort codecs for several 10 - {{:https://github.com/zarr-conventions}zarr conventions}: geo-proj, 11 - spatial, multiscales, and geoembeddings. 5 + This library provides {!Jsont.t} codecs for decoding and encoding the JSON 6 + metadata used by 7 + {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html}Zarr v2} and 8 + {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html}Zarr v3} 9 + stores. It also includes best-effort codecs for several 10 + {{:https://github.com/zarr-conventions}zarr conventions}: geo-proj, spatial, 11 + multiscales, and geoembeddings. 12 12 13 - All types use polymorphic variants. Known extensions and codecs are 14 - enumerated with an [`Other] escape hatch for unrecognised values. 15 - Unknown JSON fields are preserved throughout via 16 - {!Jsont.Object.keep_unknown} so that round-tripping is faithful. 13 + All types use polymorphic variants. Known extensions and codecs are 14 + enumerated with an [`Other] escape hatch for unrecognised values. Unknown 15 + JSON fields are preserved throughout via {!Jsont.Object.keep_unknown} so 16 + that round-tripping is faithful. 17 17 18 18 {2 Quick start} 19 19 ··· 41 41 42 42 Types used by both Zarr v2 and v3 metadata. *) 43 43 44 + type fill_value = 45 + [ `Null 46 + | `Bool of bool 47 + | `Int of int64 48 + | `Float of float 49 + | `Complex of float * float 50 + | `Bytes of string ] 44 51 (** The value stored in uninitialized or missing chunks. 45 52 46 53 In JSON, fill values appear as multiple sorts: ··· 54 61 55 62 See 56 63 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#fill-value}v3 57 - fill value} and 64 + fill value} and 58 65 {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html#fill-value}v2 59 - fill value}. *) 60 - type fill_value = [ 61 - | `Null 62 - | `Bool of bool 63 - | `Int of int64 64 - | `Float of float 65 - | `Complex of float * float 66 - | `Bytes of string 67 - ] 66 + fill value}. *) 68 67 69 68 val fill_value_jsont : fill_value Jsont.t 70 - (** Codec for {!fill_value}. Dispatches on the JSON sort via 71 - {!Jsont.any}: null, boolean, number, string, and array are each 72 - routed to a specialised sub-codec. *) 69 + (** Codec for {!fill_value}. Dispatches on the JSON sort via {!Jsont.any}: null, 70 + boolean, number, string, and array are each routed to a specialised 71 + sub-codec. *) 73 72 73 + type endian = [ `Little | `Big | `Not_applicable ] 74 74 (** Byte order indicator from a NumPy dtype typestr. 75 75 - [`Little] — ['<'] little-endian 76 76 - [`Big] — ['>'] big-endian 77 77 - [`Not_applicable] — ['|'] or ['='], used for single-byte types *) 78 - type endian = [ `Little | `Big | `Not_applicable ] 79 78 79 + type dtype = 80 + [ `Bool 81 + | `Int of endian * int (** Signed integer; size in bytes. *) 82 + | `Uint of endian * int (** Unsigned integer; size in bytes. *) 83 + | `Float of endian * int (** IEEE float; size in bytes. *) 84 + | `Complex of endian * int (** Complex float pair; total size in bytes. *) 85 + | `Timedelta of endian * string (** Time delta; unit string (e.g. ["s"]). *) 86 + | `Datetime of endian * string (** Datetime; unit string (e.g. ["ns"]). *) 87 + | `String of int (** Fixed-length byte string; size in bytes. *) 88 + | `Unicode of endian * int (** Fixed-length unicode; number of characters. *) 89 + | `Raw of int (** Void / raw bytes; size in bytes. *) 90 + | `Structured of (string * dtype * int list option) list 91 + (** Compound type: list of [(field_name, field_dtype, optional_shape)]. *) 92 + ] 80 93 (** NumPy array dtype as used in Zarr v2 81 94 {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html#data-type-encoding} 82 - array metadata}. 95 + array metadata}. 83 96 84 97 Simple types are encoded as JSON strings in 85 98 {{:https://numpy.org/doc/stable/reference/arrays.interface.html#arrays-interface} 86 - NumPy typestr} format: a one-character byte-order indicator (['<'], 87 - ['>'], or ['|']), a one-character type code, and a size in bytes. 88 - For example: 99 + NumPy typestr} format: a one-character byte-order indicator (['<'], ['>'], 100 + or ['|']), a one-character type code, and a size in bytes. For example: 89 101 - ["<f8"] — little-endian 64-bit float 90 102 - ["|b1"] — boolean 91 103 - ["<M8[ns]"] — little-endian datetime with nanosecond units 92 104 93 - Structured (compound) types are encoded as JSON arrays of field 94 - descriptors: [[\["name","<f4"\], \["name","<i2",\[3\]\]]]. Each 95 - field has a name, a dtype (which may itself be structured), and an 96 - optional shape. *) 97 - type dtype = [ 98 - | `Bool 99 - | `Int of endian * int (** Signed integer; size in bytes. *) 100 - | `Uint of endian * int (** Unsigned integer; size in bytes. *) 101 - | `Float of endian * int (** IEEE float; size in bytes. *) 102 - | `Complex of endian * int (** Complex float pair; total size in bytes. *) 103 - | `Timedelta of endian * string (** Time delta; unit string (e.g. ["s"]). *) 104 - | `Datetime of endian * string (** Datetime; unit string (e.g. ["ns"]). *) 105 - | `String of int (** Fixed-length byte string; size in bytes. *) 106 - | `Unicode of endian * int (** Fixed-length unicode; number of characters. *) 107 - | `Raw of int (** Void / raw bytes; size in bytes. *) 108 - | `Structured of (string * dtype * int list option) list 109 - (** Compound type: list of [(field_name, field_dtype, optional_shape)]. *) 110 - ] 105 + Structured (compound) types are encoded as JSON arrays of field descriptors: 106 + [[["name","<f4"], ["name","<i2",[3]]]]. Each field has a name, a dtype 107 + (which may itself be structured), and an optional shape. *) 111 108 112 109 val dtype_jsont : dtype Jsont.t 113 - (** Codec for {!dtype}. Simple types round-trip through JSON strings; 114 - structured types round-trip through JSON arrays. The codec is 115 - recursive: structured field dtypes may themselves be structured. *) 110 + (** Codec for {!dtype}. Simple types round-trip through JSON strings; structured 111 + types round-trip through JSON arrays. The codec is recursive: structured 112 + field dtypes may themselves be structured. *) 116 113 117 114 (** {1:escape Escape-hatch types} 118 115 119 - Catch-all types for unrecognised codecs and extensions, ensuring 120 - that unknown values are preserved and round-tripped faithfully. *) 116 + Catch-all types for unrecognised codecs and extensions, ensuring that 117 + unknown values are preserved and round-tripped faithfully. *) 121 118 122 119 (** Unrecognised Zarr v2 codec (compressor or filter). 123 120 124 - V2 codecs are JSON objects with an ["id"] key naming the codec and 125 - arbitrary additional configuration fields. For example: 126 - {[{"id": "custom_codec", "param1": 42, "param2": "hello"}]} 121 + V2 codecs are JSON objects with an ["id"] key naming the codec and arbitrary 122 + additional configuration fields. For example: 123 + {[ 124 + {"id": "custom_codec", "param1": 42, "param2": "hello"} 125 + ]} 127 126 128 - Unknown fields are captured via {!Jsont.Object.keep_unknown} and 129 - preserved on re-encoding. *) 127 + Unknown fields are captured via {!Jsont.Object.keep_unknown} and preserved 128 + on re-encoding. *) 130 129 module Other_codec : sig 131 130 type t 132 131 ··· 142 141 143 142 (** Unrecognised Zarr v3 extension point. 144 143 145 - V3 uses a uniform extension format for data types, chunk grids, chunk 146 - key encodings, codecs, and storage transformers. Each is a JSON 147 - object with: 144 + V3 uses a uniform extension format for data types, chunk grids, chunk key 145 + encodings, codecs, and storage transformers. Each is a JSON object with: 148 146 - ["name"] — extension identifier 149 147 - ["configuration"] — optional configuration object 150 148 - ["must_understand"] — boolean (default [true]); if [false], ··· 152 150 153 151 See 154 152 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#extension-points} 155 - v3 extension points}. *) 153 + v3 extension points}. *) 156 154 module Other_ext : sig 157 155 type t 158 156 ··· 163 161 (** The extension configuration, if any. *) 164 162 165 163 val must_understand : t -> bool 166 - (** Whether implementations must understand this extension. Defaults 167 - to [true] when absent in JSON; omitted on encode when [true]. *) 164 + (** Whether implementations must understand this extension. Defaults to [true] 165 + when absent in JSON; omitted on encode when [true]. *) 168 166 169 167 val make : string -> Jsont.json option -> bool -> t 170 168 val jsont : t Jsont.t ··· 173 171 (** {1:v3 Zarr v3} 174 172 175 173 Types and codecs for 176 - {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html} 177 - Zarr v3} metadata. V3 stores a single [zarr.json] file per node 178 - (array or group), with the ["node_type"] field distinguishing the 179 - two. *) 174 + {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html} Zarr v3} 175 + metadata. V3 stores a single [zarr.json] file per node (array or group), 176 + with the ["node_type"] field distinguishing the two. *) 180 177 module V3 : sig 181 - 182 178 (** {2 Codecs} 183 179 184 180 A v3 array's data is processed through a 185 181 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#codecs} 186 - codec chain}: zero or more array-to-array codecs, then exactly one 187 - array-to-bytes codec, then zero or more bytes-to-bytes codecs. 188 - Each codec is a JSON object with ["name"] and optional 189 - ["configuration"]. *) 182 + codec chain}: zero or more array-to-array codecs, then exactly one 183 + array-to-bytes codec, then zero or more bytes-to-bytes codecs. Each codec 184 + is a JSON object with ["name"] and optional ["configuration"]. *) 190 185 module Codec : sig 191 - 192 186 (** The 193 187 {{:https://zarr-specs.readthedocs.io/en/latest/v3/codecs/bytes/index.html} 194 - bytes} codec (array-to-bytes). Serialises array elements in 195 - lexicographic (C) order. The [endian] field specifies byte order; 196 - it is omitted for single-byte data types. *) 188 + bytes} codec (array-to-bytes). Serialises array elements in 189 + lexicographic (C) order. The [endian] field specifies byte order; it is 190 + omitted for single-byte data types. *) 197 191 module Bytes : sig 198 192 type t 193 + 199 194 val endian : t -> [ `Little | `Big ] option 200 - (** [None] when endian is not applicable (single-byte data types 201 - such as [bool] or [uint8]). *) 195 + (** [None] when endian is not applicable (single-byte data types such as 196 + [bool] or [uint8]). *) 202 197 end 203 198 204 199 (** The 205 200 {{:https://zarr-specs.readthedocs.io/en/latest/v3/codecs/gzip/index.html} 206 - gzip} codec (bytes-to-bytes). Compresses data using the gzip 207 - algorithm. *) 201 + gzip} codec (bytes-to-bytes). Compresses data using the gzip algorithm. 202 + *) 208 203 module Gzip : sig 209 204 type t 205 + 210 206 val level : t -> int 211 207 (** Compression level, 0 (no compression) to 9 (best). *) 212 208 end 213 209 214 210 (** The 215 211 {{:https://zarr-specs.readthedocs.io/en/latest/v3/codecs/blosc/index.html} 216 - blosc} codec (bytes-to-bytes). Meta-compressor that delegates 217 - to one of several compression libraries. *) 212 + blosc} codec (bytes-to-bytes). Meta-compressor that delegates to one of 213 + several compression libraries. *) 218 214 module Blosc : sig 219 215 type t 216 + 220 217 val cname : t -> string 221 218 (** Compressor name: ["lz4"], ["lz4hc"], ["blosclz"], ["zstd"], 222 219 ["snappy"], or ["zlib"]. *) ··· 228 225 (** Shuffle mode applied before compression. *) 229 226 230 227 val typesize : t -> int option 231 - (** Element size in bytes for shuffling. [None] when shuffle is 228 + (** Element size in bytes for shuffling. [None] when shuffle is 232 229 [`Noshuffle]. *) 233 230 234 231 val blocksize : t -> int ··· 237 234 238 235 (** The 239 236 {{:https://zarr-specs.readthedocs.io/en/latest/v3/codecs/transpose/index.html} 240 - transpose} codec (array-to-array). Permutes array dimensions. *) 237 + transpose} codec (array-to-array). Permutes array dimensions. *) 241 238 module Transpose : sig 242 239 type t 240 + 243 241 val order : t -> int list 244 - (** Dimension permutation, e.g. [\[1; 0; 2\]]. *) 242 + (** Dimension permutation, e.g. [[1; 0; 2]]. *) 245 243 end 246 244 247 245 (** The 248 246 {{:https://zarr-specs.readthedocs.io/en/latest/v3/codecs/sharding-indexed/index.html} 249 - sharding} codec (array-to-bytes). Bundles multiple inner chunks 250 - into a single shard with an embedded index for random access. 251 - The codec is recursive: inner chunks have their own codec chain. *) 247 + sharding} codec (array-to-bytes). Bundles multiple inner chunks into a 248 + single shard with an embedded index for random access. The codec is 249 + recursive: inner chunks have their own codec chain. *) 252 250 module Sharding : sig 253 251 type t 254 - and codec = [ 255 - | `Bytes of Bytes.t 252 + 253 + and codec = 254 + [ `Bytes of Bytes.t 256 255 | `Gzip of Gzip.t 257 256 | `Blosc of Blosc.t 258 257 | `Crc32c 259 258 | `Transpose of Transpose.t 260 259 | `Sharding of t 261 - | `Other of Other_ext.t 262 - ] 260 + | `Other of Other_ext.t ] 261 + 263 262 val chunk_shape : t -> int list 264 263 (** Shape of inner chunks within each shard. *) 265 264 ··· 267 266 (** Codec chain applied to each inner chunk. *) 268 267 269 268 val index_codecs : t -> codec list 270 - (** Codec chain for the shard index. Empty list if unspecified. *) 269 + (** Codec chain for the shard index. Empty list if unspecified. *) 271 270 272 271 val index_location : t -> [ `Start | `End ] 273 - (** Where the shard index is stored. Default [`End]. *) 272 + (** Where the shard index is stored. Default [`End]. *) 274 273 end 275 274 end 276 275 277 - (** A v3 codec pipeline entry. The core specification defines six 278 - codecs; unrecognised codecs decode as [`Other]. 276 + type codec = Codec.Sharding.codec 277 + (** A v3 codec pipeline entry. The core specification defines six codecs; 278 + unrecognised codecs decode as [`Other]. 279 279 280 280 - [`Bytes] — array-to-bytes serialisation 281 281 - [`Gzip] — gzip compression ··· 283 283 - [`Crc32c] — CRC-32C checksum (no configuration) 284 284 - [`Transpose] — dimension permutation 285 285 - [`Sharding] — sharding with inner chunks *) 286 - type codec = Codec.Sharding.codec 287 286 288 287 val codec_jsont : codec Jsont.t 289 - (** Codec for {!codec}. Dispatches on the ["name"] field. 290 - Sharding codecs are decoded recursively so that inner codec 291 - chains are fully typed. *) 288 + (** Codec for {!codec}. Dispatches on the ["name"] field. Sharding codecs are 289 + decoded recursively so that inner codec chains are fully typed. *) 292 290 293 291 (** V3 294 292 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#data-type} 295 - data type}. Core types are encoded as JSON strings; extension 296 - types as JSON objects with ["name"] and ["configuration"]. 293 + data type}. Core types are encoded as JSON strings; extension types as 294 + JSON objects with ["name"] and ["configuration"]. 297 295 298 296 The fifteen core types are: 299 297 - Booleans: [bool] ··· 304 302 305 303 Raw bit types ([r8], [r16], etc.) use the ["r<bits>"] pattern. *) 306 304 module Data_type : sig 307 - type t = [ 308 - | `Bool | `Int8 | `Int16 | `Int32 | `Int64 309 - | `Uint8 | `Uint16 | `Uint32 | `Uint64 310 - | `Float16 | `Float32 | `Float64 311 - | `Complex64 | `Complex128 312 - | `Raw of int (** Raw bits; the integer is the bit width. *) 313 - | `Other of Other_ext.t (** Extension data type. *) 314 - ] 305 + type t = 306 + [ `Bool 307 + | `Int8 308 + | `Int16 309 + | `Int32 310 + | `Int64 311 + | `Uint8 312 + | `Uint16 313 + | `Uint32 314 + | `Uint64 315 + | `Float16 316 + | `Float32 317 + | `Float64 318 + | `Complex64 319 + | `Complex128 320 + | `Raw of int (** Raw bits; the integer is the bit width. *) 321 + | `Other of Other_ext.t (** Extension data type. *) ] 315 322 end 316 323 317 324 val data_type_jsont : Data_type.t Jsont.t 318 - (** Codec for {!Data_type.t}. Core types decode from JSON strings; 319 - extension types from JSON objects. The ["r<bits>"] pattern 320 - decodes as [`Raw bits]. *) 325 + (** Codec for {!Data_type.t}. Core types decode from JSON strings; extension 326 + types from JSON objects. The ["r<bits>"] pattern decodes as [`Raw bits]. 327 + *) 321 328 322 329 (** V3 323 330 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#chunk-grid} 324 - chunk grid}. Defines how the array is divided into chunks. 325 - The only core grid is ["regular"] (fixed-shape chunks). *) 331 + chunk grid}. Defines how the array is divided into chunks. The only core 332 + grid is ["regular"] (fixed-shape chunks). *) 326 333 module Chunk_grid : sig 327 334 (** Regular chunk grid: every chunk has the same shape. *) 328 335 module Regular : sig 329 336 type t 337 + 330 338 val chunk_shape : t -> int list 331 - (** Dimensions of each chunk, e.g. [\[1000; 100\]]. *) 339 + (** Dimensions of each chunk, e.g. [[1000; 100]]. *) 332 340 end 333 341 334 342 type t = [ `Regular of Regular.t | `Other of Other_ext.t ] 335 343 end 336 344 337 345 val chunk_grid_jsont : Chunk_grid.t Jsont.t 338 - (** Codec for {!Chunk_grid.t}. Dispatches on the ["name"] field. *) 346 + (** Codec for {!Chunk_grid.t}. Dispatches on the ["name"] field. *) 339 347 340 348 (** V3 341 349 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#chunk-key-encoding} 342 - chunk key encoding}. Maps chunk grid coordinates to store keys. 343 - The only core encoding is ["default"]. *) 350 + chunk key encoding}. Maps chunk grid coordinates to store keys. The only 351 + core encoding is ["default"]. *) 344 352 module Chunk_key_encoding : sig 345 - (** Default key encoding. Chunk at grid position [(1, 2, 3)] is 346 - stored at key ["c/1/2/3"] (with ["/"]) or ["c.1.2.3"] (with 347 - ["."]). The prefix ["c"] distinguishes chunk keys from 348 - metadata keys. *) 353 + (** Default key encoding. Chunk at grid position [(1, 2, 3)] is stored at 354 + key ["c/1/2/3"] (with ["/"]) or ["c.1.2.3"] (with ["."]). The prefix 355 + ["c"] distinguishes chunk keys from metadata keys. *) 349 356 module Default : sig 350 357 type t 358 + 351 359 val separator : t -> [ `Slash | `Dot ] 352 - (** The separator between coordinate components. 353 - Default is [`Slash]. *) 360 + (** The separator between coordinate components. Default is [`Slash]. *) 354 361 end 355 362 356 363 type t = [ `Default of Default.t | `Other of Other_ext.t ] 357 364 end 358 365 359 366 val chunk_key_encoding_jsont : Chunk_key_encoding.t Jsont.t 360 - (** Codec for {!Chunk_key_encoding.t}. Dispatches on the ["name"] 361 - field. *) 367 + (** Codec for {!Chunk_key_encoding.t}. Dispatches on the ["name"] field. *) 362 368 363 369 (** Complete v3 364 370 {{:https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html#array-metadata} 365 - array metadata} as stored in [zarr.json]. 371 + array metadata} as stored in [zarr.json]. 366 372 367 - Required fields: [shape], [data_type], [chunk_grid], 368 - [chunk_key_encoding], [codecs], [fill_value]. 373 + Required fields: [shape], [data_type], [chunk_grid], [chunk_key_encoding], 374 + [codecs], [fill_value]. 369 375 370 - Optional fields: [dimension_names] (named dimensions, with [null] 371 - entries for unnamed ones), [storage_transformers], [attributes]. *) 376 + Optional fields: [dimension_names] (named dimensions, with [null] entries 377 + for unnamed ones), [storage_transformers], [attributes]. *) 372 378 module Array_meta : sig 373 379 type t 374 380 375 381 val shape : t -> int list 376 - (** Array dimensions, e.g. [\[10000; 1000\]]. *) 382 + (** Array dimensions, e.g. [[10000; 1000]]. *) 377 383 378 384 val data_type : t -> Data_type.t 379 385 (** Element data type. *) ··· 391 397 (** Default value for uninitialised chunks. *) 392 398 393 399 val dimension_names : t -> string option list option 394 - (** Named dimensions. [None] if absent; [Some \[Some "x"; None\]] 395 - if partially named. *) 400 + (** Named dimensions. [None] if absent; [Some [Some "x"; None]] if partially 401 + named. *) 396 402 397 403 val storage_transformers : t -> Other_ext.t list option 398 404 (** Optional storage transformer extensions. *) ··· 402 408 end 403 409 404 410 val array_meta_jsont : Array_meta.t Jsont.t 405 - (** Codec for {!Array_meta.t}. Consumes ["zarr_format"] and 406 - ["node_type"] on decode (always writes [3] / ["array"] on encode). 407 - The ["attributes"] sub-object is consumed but decoded separately 408 - at the {!V3_node} level. *) 411 + (** Codec for {!Array_meta.t}. Consumes ["zarr_format"] and ["node_type"] on 412 + decode (always writes [3] / ["array"] on encode). The ["attributes"] 413 + sub-object is consumed but decoded separately at the {!V3_node} level. *) 409 414 end 410 415 411 416 (** {1:v2 Zarr v2} 412 417 413 418 Types and codecs for 414 419 {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html}Zarr v2} 415 - metadata. V2 uses three separate files: [.zarray] (array metadata), 416 - [.zgroup] (group metadata, just [\{"zarr_format": 2\}]), and 417 - [.zattrs] (user attributes). *) 420 + metadata. V2 uses three separate files: [.zarray] (array metadata), 421 + [.zgroup] (group metadata, just [\{"zarr_format": 2\}]), and [.zattrs] (user 422 + attributes). *) 418 423 module V2 : sig 419 - 420 424 (** {2 Compressors} 421 425 422 - V2 compressors appear in the ["compressor"] field of [.zarray]. 423 - Each is a JSON object with an ["id"] field naming the compressor 424 - and codec-specific configuration. A [null] value means no 425 - compression. *) 426 + V2 compressors appear in the ["compressor"] field of [.zarray]. Each is a 427 + JSON object with an ["id"] field naming the compressor and codec-specific 428 + configuration. A [null] value means no compression. *) 426 429 module Compressor : sig 427 - 428 430 (** {{:https://www.blosc.org/}Blosc} meta-compressor. *) 429 431 module Blosc : sig 430 432 type t 433 + 431 434 val cname : t -> string 432 435 (** Compression library name (e.g. ["lz4"], ["zstd"]). *) 433 436 ··· 447 450 (** {{:https://zlib.net/}Zlib} compressor. *) 448 451 module Zlib : sig 449 452 type t 453 + 450 454 val level : t -> int 451 455 (** Compression level, 1–9. *) 452 456 ··· 454 458 end 455 459 end 456 460 457 - (** A v2 compressor. Known compressors are decoded into typed 458 - variants; unrecognised ones are captured as {!Other_codec.t}. *) 459 - type compressor = [ 460 - | `Blosc of Compressor.Blosc.t 461 + type compressor = 462 + [ `Blosc of Compressor.Blosc.t 461 463 | `Zlib of Compressor.Zlib.t 462 - | `Other of Other_codec.t 463 - ] 464 + | `Other of Other_codec.t ] 465 + (** A v2 compressor. Known compressors are decoded into typed variants; 466 + unrecognised ones are captured as {!Other_codec.t}. *) 464 467 465 468 val compressor_jsont : compressor Jsont.t 466 - (** Codec for {!compressor}. Dispatches on the ["id"] field. *) 469 + (** Codec for {!compressor}. Dispatches on the ["id"] field. *) 467 470 468 471 (** {2 Filters} 469 472 470 - V2 filters appear in the ["filters"] field of [.zarray] as a 471 - JSON array of objects (or [null] for no filters). Each object 472 - has an ["id"] field. *) 473 + V2 filters appear in the ["filters"] field of [.zarray] as a JSON array of 474 + objects (or [null] for no filters). Each object has an ["id"] field. *) 473 475 module Filter : sig 474 - 475 476 (** Delta filter: stores differences between consecutive elements. *) 476 477 module Delta : sig 477 478 type t 479 + 478 480 val dtype : t -> string 479 481 (** Data type of the input, as a NumPy typestr (e.g. ["<f8"]). *) 480 482 ··· 485 487 end 486 488 end 487 489 490 + type filter = [ `Delta of Filter.Delta.t | `Other of Other_codec.t ] 488 491 (** A v2 filter. *) 489 - type filter = [ 490 - | `Delta of Filter.Delta.t 491 - | `Other of Other_codec.t 492 - ] 493 492 494 493 val filter_jsont : filter Jsont.t 495 - (** Codec for {!filter}. Dispatches on the ["id"] field. *) 494 + (** Codec for {!filter}. Dispatches on the ["id"] field. *) 496 495 497 496 (** Complete v2 498 497 {{:https://zarr-specs.readthedocs.io/en/latest/v2/core.html#metadata} 499 - array metadata} as stored in [.zarray]. *) 498 + array metadata} as stored in [.zarray]. *) 500 499 module Array_meta : sig 501 500 type t 502 501 ··· 504 503 (** Array dimensions. *) 505 504 506 505 val chunks : t -> int list 507 - (** Chunk dimensions. All chunks have the same shape. *) 506 + (** Chunk dimensions. All chunks have the same shape. *) 508 507 509 508 val dtype : t -> dtype 510 509 (** Element data type in NumPy typestr format. *) 511 510 512 511 val compressor : t -> compressor option 513 - (** Primary compressor. [None] means no compression. *) 512 + (** Primary compressor. [None] means no compression. *) 514 513 515 514 val fill_value : t -> fill_value 516 515 (** Default value for uninitialised chunks. *) 517 516 518 517 val order : t -> [ `C | `F ] 519 - (** Memory layout: [`C] for row-major (C order), [`F] for 520 - column-major (Fortran order). *) 518 + (** Memory layout: [`C] for row-major (C order), [`F] for column-major 519 + (Fortran order). *) 521 520 522 521 val filters : t -> filter list option 523 - (** Pre-compression filter pipeline. [None] means no filters. *) 522 + (** Pre-compression filter pipeline. [None] means no filters. *) 524 523 525 524 val dimension_separator : t -> [ `Dot | `Slash ] option 526 - (** Separator used in chunk keys. [None] uses the default ["."]. *) 525 + (** Separator used in chunk keys. [None] uses the default ["."]. *) 527 526 528 527 val unknown : t -> Jsont.json 529 528 (** Extra fields preserved for round-tripping. *) 530 529 end 531 530 532 531 val array_meta_jsont : Array_meta.t Jsont.t 533 - (** Codec for {!Array_meta.t}. Consumes ["zarr_format"] on decode 534 - (always writes [2] on encode). *) 532 + (** Codec for {!Array_meta.t}. Consumes ["zarr_format"] on decode (always 533 + writes [2] on encode). *) 535 534 end 536 535 537 536 (** {1:conv Conventions} 538 537 539 - {{:https://github.com/zarr-conventions}Zarr conventions} extend the 540 - base metadata with domain-specific attributes. Each convention uses 541 - a namespace prefix (e.g. ["proj:"], ["spatial:"]) and registers 542 - itself in the ["zarr_conventions"] array within the attributes 543 - object. 538 + {{:https://github.com/zarr-conventions}Zarr conventions} extend the base 539 + metadata with domain-specific attributes. Each convention uses a namespace 540 + prefix (e.g. ["proj:"], ["spatial:"]) and registers itself in the 541 + ["zarr_conventions"] array within the attributes object. 544 542 545 - This library provides typed codecs for four conventions. Each 546 - sub-module exposes a {!Conv.Meta.t} constant for registration and a 547 - [jsont] codec that decodes from the flat attributes object (using 548 - {!Jsont.Object.skip_unknown} to coexist with other conventions). *) 543 + This library provides typed codecs for four conventions. Each sub-module 544 + exposes a {!Conv.Meta.t} constant for registration and a [jsont] codec that 545 + decodes from the flat attributes object (using {!Jsont.Object.skip_unknown} 546 + to coexist with other conventions). *) 549 547 module Conv : sig 550 - 551 - (** Convention registration metadata, as stored in the 552 - ["zarr_conventions"] array. At least one of [uuid], [schema_url], 553 - or [spec_url] should be present for identification. *) 548 + (** Convention registration metadata, as stored in the ["zarr_conventions"] 549 + array. At least one of [uuid], [schema_url], or [spec_url] should be 550 + present for identification. *) 554 551 module Meta : sig 555 552 type t 553 + 556 554 val uuid : t -> string 557 555 (** Permanent identifier for the convention. *) 558 556 ··· 574 572 (** {{:https://github.com/zarr-experimental/geo-proj}Geo-projection} 575 573 convention ([proj:] prefix). 576 574 577 - Defines coordinate reference system (CRS) metadata for geospatial 578 - data. At least one of [code], [wkt2], or [projjson] should be 579 - present. 575 + Defines coordinate reference system (CRS) metadata for geospatial data. At 576 + least one of [code], [wkt2], or [projjson] should be present. 580 577 581 578 - [proj:code] — authority:code identifier (e.g. ["EPSG:4326"]) 582 579 - [proj:wkt2] — WKT2 (ISO 19162:2019) CRS string 583 580 - [proj:projjson] — PROJJSON CRS object *) 584 581 module Proj : sig 585 582 type t 583 + 586 584 val code : t -> string option 587 585 (** Authority:code CRS identifier, e.g. ["EPSG:4326"]. *) 588 586 ··· 602 600 (** {{:https://github.com/zarr-conventions/spatial}Spatial} convention 603 601 ([spatial:] prefix). 604 602 605 - Describes the mapping between array indices and spatial 606 - coordinates. Works for both geospatial and non-geospatial data 607 - (microscopy, medical imaging, etc.). 603 + Describes the mapping between array indices and spatial coordinates. Works 604 + for both geospatial and non-geospatial data (microscopy, medical imaging, 605 + etc.). 608 606 609 607 The affine transform maps pixel coordinates [(i, j)] to spatial 610 608 coordinates [(x, y)] via: 611 609 {[ 612 - x = a*i + b*j + c 613 - y = d*i + e*j + f 610 + x = (a * i) + (b * j) + c y = (d * i) + (e * j) + f 614 611 ]} 615 612 where the six coefficients are stored in [transform] as 616 - [\[a; b; c; d; e; f\]]. *) 613 + [[a; b; c; d; e; f]]. *) 617 614 module Spatial : sig 618 615 type t 616 + 619 617 val dimensions : t -> string list 620 618 (** Names of the spatial dimensions (e.g. [["y"; "x"]]). *) 621 619 622 620 val bbox : t -> float list option 623 - (** Bounding box: [\[xmin; ymin; xmax; ymax\]] for 2D, 624 - [\[xmin; ymin; zmin; xmax; ymax; zmax\]] for 3D. *) 621 + (** Bounding box: [[xmin; ymin; xmax; ymax]] for 2D, 622 + [[xmin; ymin; zmin; xmax; ymax; zmax]] for 3D. *) 625 623 626 624 val transform_type : t -> string option 627 - (** Type of coordinate transform. Currently only ["affine"] is 628 - defined; defaults to ["affine"] when absent. *) 625 + (** Type of coordinate transform. Currently only ["affine"] is defined; 626 + defaults to ["affine"] when absent. *) 629 627 630 628 val transform : t -> float list option 631 - (** Affine coefficients [\[a; b; c; d; e; f\]] for 2D. *) 629 + (** Affine coefficients [[a; b; c; d; e; f]] for 2D. *) 632 630 633 631 val shape : t -> int list option 634 - (** Shape of the spatial dimensions [\[height; width\]]. Useful 635 - when the spatial shape differs from the full array shape. *) 632 + (** Shape of the spatial dimensions [[height; width]]. Useful when the 633 + spatial shape differs from the full array shape. *) 636 634 637 635 val registration : t -> [ `Pixel | `Node ] option 638 - (** Grid cell registration. [`Pixel] (default) means cell 639 - boundaries align with coordinate values; [`Node] means cell 640 - centres align with coordinate values. *) 636 + (** Grid cell registration. [`Pixel] (default) means cell boundaries align 637 + with coordinate values; [`Node] means cell centres align with coordinate 638 + values. *) 641 639 642 640 val meta : Meta.t 643 641 (** Convention registration metadata (UUID ··· 647 645 end 648 646 649 647 (** {{:https://github.com/geo-embeddings/embeddings-zarr-convention} 650 - Geoembeddings} convention ([geoemb:] prefix). 648 + Geoembeddings} convention ([geoemb:] prefix). 651 649 652 - Describes geospatial embedding groups with model provenance, 653 - processing parameters, and optional quantization metadata. 654 - Supports two embedding types: 650 + Describes geospatial embedding groups with model provenance, processing 651 + parameters, and optional quantization metadata. Supports two embedding 652 + types: 655 653 656 - - {b Pixel embeddings}: per-pixel dense embeddings where each 657 - spatial location has an embedding vector. 658 - - {b Chip embeddings}: image patch embeddings where non-overlapping 659 - or overlapping regions are encoded into single vectors. 654 + - {b Pixel embeddings}: per-pixel dense embeddings where each spatial 655 + location has an embedding vector. 656 + - {b Chip embeddings}: image patch embeddings where non-overlapping or 657 + overlapping regions are encoded into single vectors. 660 658 661 - When [type_] is [`Chip], the [chip_layout] field is also 662 - required. *) 659 + When [type_] is [`Chip], the [chip_layout] field is also required. *) 663 660 module Geoemb : sig 664 - 665 - (** Chip layout for chip-type embeddings, describing how source 666 - imagery was divided into patches. *) 661 + (** Chip layout for chip-type embeddings, describing how source imagery was 662 + divided into patches. *) 667 663 module Chip_layout : sig 668 664 type t 665 + 669 666 val layout_type : t -> [ `Regular_grid | `Irregular ] 670 - (** [`Regular_grid] for uniform non-overlapping or overlapping 671 - patches; [`Irregular] for variable-size patches. *) 667 + (** [`Regular_grid] for uniform non-overlapping or overlapping patches; 668 + [`Irregular] for variable-size patches. *) 672 669 673 670 val chip_size : t -> int * int 674 671 (** Chip dimensions [(height, width)] in pixels. *) 675 672 676 673 val stride : t -> (int * int) option 677 - (** Stride [(y, x)] between chips. Defaults to [chip_size] 674 + (** Stride [(y, x)] between chips. Defaults to [chip_size] 678 675 (non-overlapping) when absent. *) 679 676 680 677 val grid_id : t -> string option ··· 684 681 (** URL to a grid definition document. *) 685 682 end 686 683 687 - (** Scale parameters for dequantizing compressed embeddings. Uses 688 - a tagged union on the ["type"] field: 684 + (** Scale parameters for dequantizing compressed embeddings. Uses a tagged 685 + union on the ["type"] field: 689 686 690 687 - {b Scalar}: [value = quantized * scale + offset] 691 - - {b Array}: [value\[..., y, x\] = quantized\[..., y, x\] * 692 - array\[..., y, x\]]; non-finite values in the scale array 693 - indicate no-data pixels. *) 688 + - {b Array}: 689 + [value[..., y, x] = quantized[..., y, x] * array[..., y, x]]; 690 + non-finite values in the scale array indicate no-data pixels. *) 694 691 module Scale : sig 695 692 (** Global scalar dequantization parameters. *) 696 693 module Scalar : sig 697 694 type t 695 + 698 696 val scale : t -> float 699 697 (** Scale factor. *) 700 698 ··· 705 703 (** Per-pixel scale factors stored in a sibling zarr array. *) 706 704 module Array_ : sig 707 705 type t 706 + 708 707 val array_name : t -> string 709 708 (** Name of the zarr array containing per-pixel scales. *) 710 709 711 710 val nodata : t -> string option 712 - (** Value indicating no-data in the scale array (e.g. 713 - ["+inf"]). Represented as a string since the JSON value 714 - may be a number or a string. *) 711 + (** Value indicating no-data in the scale array (e.g. ["+inf"]). 712 + Represented as a string since the JSON value may be a number or a 713 + string. *) 715 714 end 716 715 717 716 type t = [ `Scalar of Scalar.t | `Array of Array_.t ] 717 + 718 718 val jsont : t Jsont.t 719 719 end 720 720 721 - (** Quantization details for embeddings compressed from their 722 - original floating-point representation. *) 721 + (** Quantization details for embeddings compressed from their original 722 + floating-point representation. *) 723 723 module Quantization : sig 724 724 type t 725 + 725 726 val meth : t -> string 726 - (** Quantization method (e.g. ["linear"], 727 - ["per_pixel_scale"], ["product_quantization"], 728 - ["binary"]). *) 727 + (** Quantization method (e.g. ["linear"], ["per_pixel_scale"], 728 + ["product_quantization"], ["binary"]). *) 729 729 730 730 val original_dtype : t -> string 731 731 (** Original data type before quantization (e.g. ["float32"]). *) ··· 741 741 end 742 742 743 743 type t 744 + 744 745 val type_ : t -> [ `Pixel | `Chip ] 745 746 (** Embedding type. *) 746 747 ··· 760 761 (** Ground sample distance in metres. *) 761 762 762 763 val chip_layout : t -> Chip_layout.t option 763 - (** Chip layout configuration. Required when [type_] is [`Chip]. *) 764 + (** Chip layout configuration. Required when [type_] is [`Chip]. *) 764 765 765 766 val quantization : t -> Quantization.t option 766 767 (** Quantization details, if embeddings have been compressed. *) 767 768 768 769 val spatial_layout : t -> string option 769 - (** Spatial organisation scheme: ["utm_zones"] (one group per UTM 770 - zone, named [utm01]–[utm60]) or ["global"]. *) 770 + (** Spatial organisation scheme: ["utm_zones"] (one group per UTM zone, 771 + named [utm01]–[utm60]) or ["global"]. *) 771 772 772 773 val build_version : t -> string option 773 774 (** Version of the software that built this store. *) ··· 785 786 (** {{:https://github.com/zarr-conventions/multiscales}Multiscales} 786 787 convention. 787 788 788 - Encodes multi-resolution pyramid metadata for hierarchical data 789 - stored in zarr groups. Each level in the pyramid is a separate 790 - zarr array (or group containing arrays), linked by relative 791 - coordinate transforms. 789 + Encodes multi-resolution pyramid metadata for hierarchical data stored in 790 + zarr groups. Each level in the pyramid is a separate zarr array (or group 791 + containing arrays), linked by relative coordinate transforms. 792 792 793 - The [layout] array describes the pyramid levels. Each level has 794 - an [asset] path (relative to the group), an optional 795 - [derived_from] path, and a [transform] with [scale] and 796 - [translation] vectors describing the coordinate relationship to 797 - the source level. *) 793 + The [layout] array describes the pyramid levels. Each level has an [asset] 794 + path (relative to the group), an optional [derived_from] path, and a 795 + [transform] with [scale] and [translation] vectors describing the 796 + coordinate relationship to the source level. *) 798 797 module Multiscales : sig 799 - 800 798 (** Relative coordinate transform between pyramid levels. *) 801 799 module Transform : sig 802 800 type t 801 + 803 802 val scale : t -> float list option 804 - (** Scale factors per axis. [> 1.0] = downsampling. *) 803 + (** Scale factors per axis. [> 1.0] = downsampling. *) 805 804 806 805 val translation : t -> float list option 807 806 (** Translation offsets per axis in coordinate space. *) ··· 814 813 (** A single pyramid level. *) 815 814 module Layout_item : sig 816 815 type t 816 + 817 817 val asset : t -> string 818 - (** Path to the zarr array or group for this level, relative to 819 - the parent group (e.g. ["0"], ["r10m"], ["0/data"]). *) 818 + (** Path to the zarr array or group for this level, relative to the parent 819 + group (e.g. ["0"], ["r10m"], ["0/data"]). *) 820 820 821 821 val derived_from : t -> string option 822 822 (** Path to the source level this one was derived from. *) 823 823 824 824 val transform : t -> Transform.t option 825 - (** Coordinate transform relative to [derived_from]. Required 826 - when [derived_from] is present. *) 825 + (** Coordinate transform relative to [derived_from]. Required when 826 + [derived_from] is present. *) 827 827 828 828 val resampling_method : t -> string option 829 - (** Resampling method used to derive this level (e.g. 830 - ["average"], ["nearest"], ["bilinear"]). Overrides the 831 - top-level default. *) 829 + (** Resampling method used to derive this level (e.g. ["average"], 830 + ["nearest"], ["bilinear"]). Overrides the top-level default. *) 832 831 833 832 val unknown : t -> Jsont.json 834 - (** Additional fields (e.g. [spatial:shape], 835 - [spatial:transform]). *) 833 + (** Additional fields (e.g. [spatial:shape], [spatial:transform]). *) 836 834 end 837 835 838 836 type t 837 + 839 838 val layout : t -> Layout_item.t list 840 839 (** The pyramid levels, from highest to lowest resolution. *) 841 840 ··· 853 852 (** {1:attrs Attributes} 854 853 855 854 The composable attributes layer shared by all zarr node types. 856 - Convention-namespaced keys are routed to the appropriate convention 857 - codec; remaining keys are preserved in {!Attrs.unknown}. *) 855 + Convention-namespaced keys are routed to the appropriate convention codec; 856 + remaining keys are preserved in {!Attrs.unknown}. *) 858 857 module Attrs : sig 859 858 type t 860 859 ··· 883 882 val attrs_jsont : Attrs.t Jsont.t 884 883 (** Codec for {!Attrs.t}. 885 884 886 - On decode, routes convention-prefixed keys to sub-codecs. On 887 - encode, auto-populates ["zarr_conventions"] from whichever 888 - conventions are [Some], then merges their flat members alongside 889 - ["multiscales"] and unknown keys. *) 885 + On decode, routes convention-prefixed keys to sub-codecs. On encode, 886 + auto-populates ["zarr_conventions"] from whichever conventions are [Some], 887 + then merges their flat members alongside ["multiscales"] and unknown keys. 888 + *) 890 889 891 890 (** {1:nodes Nodes} 892 891 893 - A zarr node is either an array or a group, with associated 894 - attributes. *) 892 + A zarr node is either an array or a group, with associated attributes. *) 895 893 896 894 (** A Zarr v2 node. *) 897 895 module V2_node : sig 898 896 type t 897 + 899 898 val kind : t -> [ `Array of V2.Array_meta.t | `Group ] 900 899 (** [`Array] for [.zarray], [`Group] for [.zgroup]. *) 901 900 ··· 908 907 (** A Zarr v3 node. *) 909 908 module V3_node : sig 910 909 type t 910 + 911 911 val kind : t -> [ `Array of V3.Array_meta.t | `Group ] 912 912 (** [`Array] if ["node_type"] is ["array"], [`Group] otherwise. *) 913 913 ··· 918 918 end 919 919 920 920 val v2_array_jsont : V2_node.t Jsont.t 921 - (** Codec for a Zarr v2 [.zarray] file. Produces a {!V2_node.t} with 922 - [`Array] kind. Attributes are not decoded (use {!attrs_jsont} 923 - separately on the [.zattrs] file). *) 921 + (** Codec for a Zarr v2 [.zarray] file. Produces a {!V2_node.t} with [`Array] 922 + kind. Attributes are not decoded (use {!attrs_jsont} separately on the 923 + [.zattrs] file). *) 924 924 925 925 val v2_group_jsont : V2_node.t Jsont.t 926 - (** Codec for a Zarr v2 [.zgroup] file. Produces a {!V2_node.t} 927 - with [`Group] kind. Encodes as [{"zarr_format": 2}]. *) 926 + (** Codec for a Zarr v2 [.zgroup] file. Produces a {!V2_node.t} with [`Group] 927 + kind. Encodes as [{"zarr_format": 2}]. *) 928 928 929 929 val v3_jsont : V3_node.t Jsont.t 930 - (** Codec for a Zarr v3 [zarr.json] file. Dispatches on ["node_type"]: 931 - arrays are fully decoded via {!V3.array_meta_jsont}; groups produce 932 - a [`Group] node. The ["attributes"] sub-object is decoded via 933 - {!attrs_jsont}. *) 930 + (** Codec for a Zarr v3 [zarr.json] file. Dispatches on ["node_type"]: arrays 931 + are fully decoded via {!V3.array_meta_jsont}; groups produce a [`Group] 932 + node. The ["attributes"] sub-object is decoded via {!attrs_jsont}. *) 934 933 935 934 (** {1:dispatch Unified dispatch} *) 936 935 ··· 938 937 (** A zarr node of either version. *) 939 938 940 939 val jsont : t Jsont.t 941 - (** Top-level dispatch codec. Inspects ["zarr_format"] to choose v2 or 942 - v3, then dispatches to the appropriate node codec. V2 arrays are 943 - distinguished from groups by the presence of ["shape"]. *) 940 + (** Top-level dispatch codec. Inspects ["zarr_format"] to choose v2 or v3, then 941 + dispatches to the appropriate node codec. V2 arrays are distinguished from 942 + groups by the presence of ["shape"]. *) 944 943 945 944 (** {1:consolidated Consolidated metadata} 946 945 947 - Consolidated metadata allows loading the metadata for an entire 948 - hierarchy with a single read, avoiding per-node HTTP requests for 949 - remote stores. *) 946 + Consolidated metadata allows loading the metadata for an entire hierarchy 947 + with a single read, avoiding per-node HTTP requests for remote stores. *) 950 948 951 - (** V3 consolidated metadata, stored inline in a group's [zarr.json] 952 - as an optional ["consolidated_metadata"] field. 949 + (** V3 consolidated metadata, stored inline in a group's [zarr.json] as an 950 + optional ["consolidated_metadata"] field. 953 951 954 - See {{:https://github.com/zarr-developers/zarr-specs/pull/309} 955 - zarr-specs PR 309}. The ["metadata"] map uses relative paths as 956 - keys and full [zarr.json] objects as values. For example, a 957 - hierarchy [A/B/x] consolidated at [A] would have key ["B/x"]. *) 952 + See 953 + {{:https://github.com/zarr-developers/zarr-specs/pull/309} zarr-specs PR 954 + 309}. The ["metadata"] map uses relative paths as keys and full [zarr.json] 955 + objects as values. For example, a hierarchy [A/B/x] consolidated at [A] 956 + would have key ["B/x"]. *) 958 957 module Consolidated : sig 959 958 type t 959 + 960 960 val metadata : t -> (string * V3_node.t) list 961 961 (** Mapping from relative node path to decoded metadata. *) 962 962 963 963 val kind : t -> string 964 - (** Storage kind. Currently always ["inline"]. *) 964 + (** Storage kind. Currently always ["inline"]. *) 965 965 966 966 val jsont : t Jsont.t 967 967 end 968 968 969 - (** V2 consolidated metadata, stored in a [.zmetadata] file at the 970 - store root. 969 + (** V2 consolidated metadata, stored in a [.zmetadata] file at the store root. 971 970 972 971 The file contains a ["metadata"] object mapping flat keys like 973 - ["array1/.zarray"] and ["array1/.zattrs"] to their JSON contents, 974 - plus a ["zarr_consolidated_format"] version number (currently [1]). 975 - This codec groups the flat keys by path prefix and decodes each 976 - group into a {!V2_node.t} with optional {!Attrs.t}. *) 972 + ["array1/.zarray"] and ["array1/.zattrs"] to their JSON contents, plus a 973 + ["zarr_consolidated_format"] version number (currently [1]). This codec 974 + groups the flat keys by path prefix and decodes each group into a 975 + {!V2_node.t} with optional {!Attrs.t}. *) 977 976 module V2_consolidated : sig 978 977 type entry = { 979 - path : string; (** Relative path within the store. *) 978 + path : string; (** Relative path within the store. *) 980 979 node : V2_node.t; (** Decoded node metadata. *) 981 980 attrs : Attrs.t option; (** Decoded [.zattrs], if present. *) 982 981 } 983 982 984 983 type t 984 + 985 985 val entries : t -> entry list 986 986 (** All entries, sorted by path. *) 987 987 ··· 996 996 type probe_result = { 997 997 node : t; 998 998 attrs : Attrs.t option; 999 - (** For v2, the separately-fetched [.zattrs] if present. For v3, 1000 - [None] (attributes are inline in [zarr.json]). *) 999 + (** For v2, the separately-fetched [.zattrs] if present. For v3, [None] 1000 + (attributes are inline in [zarr.json]). *) 1001 1001 consolidated : [ `V3 of Consolidated.t | `V2 of V2_consolidated.t ] option; 1002 - (** Consolidated metadata, if present. *) 1002 + (** Consolidated metadata, if present. *) 1003 1003 children : (string * probe_result) list; 1004 - (** Recursively probed children. Populated from consolidated 1005 - metadata when available. *) 1004 + (** Recursively probed children. Populated from consolidated metadata when 1005 + available. *) 1006 1006 } 1007 1007 (** The result of probing a zarr store path. *) 1008 1008 ··· 1012 1012 (probe_result, string) result 1013 1013 (** [probe ~read path] probes the zarr store rooted at [path]. 1014 1014 1015 - [read relpath] fetches a file relative to the store root. It 1016 - should return [Ok contents] or [Error msg]. 1015 + [read relpath] fetches a file relative to the store root. It should return 1016 + [Ok contents] or [Error msg]. 1017 1017 1018 1018 Probing order: 1019 1019 + [zarr.json] (v3), checking for ["consolidated_metadata"] 1020 1020 + [.zarray] (v2 array), with optional [.zattrs] 1021 1021 + [.zgroup] (v2 group), with optional [.zattrs] and [.zmetadata] 1022 1022 1023 - When consolidated metadata is present, {!probe_result.children} is 1024 - populated by recursively grouping entries by path component. 1023 + When consolidated metadata is present, {!probe_result.children} is populated 1024 + by recursively grouping entries by path component. 1025 1025 1026 1026 Returns [Error] if no zarr metadata files can be read. *) 1027 1027 ··· 1040 1040 (** Pretty-print decoded attributes: conventions, then unknown keys. *) 1041 1041 1042 1042 val pp_probe_result : Format.formatter -> probe_result -> unit 1043 - (** Pretty-print a probe result as a tree with types, shapes, 1044 - conventions, and unknown attributes. Example output: 1045 - {v 1046 - [group] 1047 - geoemb: pixel 128d model=https://... dtype=int8 gsd=10 1048 - quantization: per_pixel_scale float32 -> int8 scale_array=scales 1049 - utm01 [group] 1050 - proj: code=EPSG:32601 1051 - spatial: dims=[y,x] bbox=[...] transform=[...] shape=[1290240x65536] 1052 - embeddings [array int8 9x128x1290240x65536] 1053 - v} *) 1043 + (** Pretty-print a probe result as a tree with types, shapes, conventions, and 1044 + unknown attributes. *)
+210 -158
test/test_zarr_jsont.ml
··· 2 2 [@@@ai_model "claude-opus-4"] 3 3 [@@@ai_provider "Anthropic"] 4 4 5 - let decode c s = match Jsont_bytesrw.decode_string c s with 6 - | Ok v -> v | Error e -> failwith e 5 + let decode c s = 6 + match Jsont_bytesrw.decode_string c s with Ok v -> v | Error e -> failwith e 7 7 8 - let encode c v = match Jsont_bytesrw.encode_string c v with 9 - | Ok s -> s | Error e -> failwith e 8 + let encode c v = 9 + match Jsont_bytesrw.encode_string c v with Ok s -> s | Error e -> failwith e 10 10 11 11 let test_other_codec () = 12 12 let json = {|{"id":"custom_codec","param1":42,"param2":"hello"}|} in ··· 18 18 print_endline "test_other_codec: ok" 19 19 20 20 let test_other_ext () = 21 - let json = {|{"name":"custom.ext","configuration":{"key":"val"},"must_understand":false}|} in 21 + let json = 22 + {|{"name":"custom.ext","configuration":{"key":"val"},"must_understand":false}|} 23 + in 22 24 let v = decode Zarr_jsont.Other_ext.jsont json in 23 25 assert (Zarr_jsont.Other_ext.name v = "custom.ext"); 24 26 assert (Zarr_jsont.Other_ext.must_understand v = false); ··· 94 96 (* structured *) 95 97 let v = decode dt {|[["x","<f4"],["y","<f4",[3]]]|} in 96 98 (match v with 97 - | `Structured fields -> 98 - assert (List.length fields = 2); 99 - let (n1, t1, s1) = List.nth fields 0 in 100 - assert (n1 = "x" && t1 = `Float (`Little, 4) && s1 = None); 101 - let (n2, t2, s2) = List.nth fields 1 in 102 - assert (n2 = "y" && t2 = `Float (`Little, 4) && s2 = Some [3]) 103 - | _ -> assert false); 99 + | `Structured fields -> 100 + assert (List.length fields = 2); 101 + let n1, t1, s1 = List.nth fields 0 in 102 + assert (n1 = "x" && t1 = `Float (`Little, 4) && s1 = None); 103 + let n2, t2, s2 = List.nth fields 1 in 104 + assert (n2 = "y" && t2 = `Float (`Little, 4) && s2 = Some [ 3 ]) 105 + | _ -> assert false); 104 106 (* roundtrip simple *) 105 107 let json' = encode dt (`Float (`Little, 8)) in 106 108 assert (decode dt json' = `Float (`Little, 8)); 107 109 (* roundtrip structured *) 108 - let s = `Structured [("x", `Float (`Little, 4), None); 109 - ("y", `Int (`Big, 2), Some [3; 2])] in 110 + let s = 111 + `Structured 112 + [ ("x", `Float (`Little, 4), None); ("y", `Int (`Big, 2), Some [ 3; 2 ]) ] 113 + in 110 114 let json' = encode dt s in 111 115 assert (decode dt json' = s); 112 116 print_endline "test_dtype: ok" ··· 117 121 let json = {|{"id":"blosc","cname":"lz4","clevel":5,"shuffle":1}|} in 118 122 let v = decode c json in 119 123 (match v with 120 - | `Blosc b -> 121 - assert (Zarr_jsont.V2.Compressor.Blosc.cname b = "lz4"); 122 - assert (Zarr_jsont.V2.Compressor.Blosc.clevel b = 5); 123 - assert (Zarr_jsont.V2.Compressor.Blosc.shuffle b = 1) 124 - | _ -> assert false); 124 + | `Blosc b -> 125 + assert (Zarr_jsont.V2.Compressor.Blosc.cname b = "lz4"); 126 + assert (Zarr_jsont.V2.Compressor.Blosc.clevel b = 5); 127 + assert (Zarr_jsont.V2.Compressor.Blosc.shuffle b = 1) 128 + | _ -> assert false); 125 129 (* zlib *) 126 130 let json = {|{"id":"zlib","level":1}|} in 127 131 let v = decode c json in 128 132 (match v with 129 - | `Zlib z -> assert (Zarr_jsont.V2.Compressor.Zlib.level z = 1) 130 - | _ -> assert false); 133 + | `Zlib z -> assert (Zarr_jsont.V2.Compressor.Zlib.level z = 1) 134 + | _ -> assert false); 131 135 (* unknown compressor *) 132 136 let json = {|{"id":"lzma","preset":6}|} in 133 137 let v = decode c json in 134 138 (match v with 135 - | `Other o -> assert (Zarr_jsont.Other_codec.name o = "lzma") 136 - | _ -> assert false); 139 + | `Other o -> assert (Zarr_jsont.Other_codec.name o = "lzma") 140 + | _ -> assert false); 137 141 print_endline "test_v2_compressor: ok" 138 142 139 143 let test_v2_filter () = ··· 141 145 let json = {|{"id":"delta","dtype":"<f8","astype":"<f4"}|} in 142 146 let v = decode f json in 143 147 (match v with 144 - | `Delta d -> 145 - assert (Zarr_jsont.V2.Filter.Delta.dtype d = "<f8"); 146 - assert (Zarr_jsont.V2.Filter.Delta.astype d = Some "<f4") 147 - | _ -> assert false); 148 + | `Delta d -> 149 + assert (Zarr_jsont.V2.Filter.Delta.dtype d = "<f8"); 150 + assert (Zarr_jsont.V2.Filter.Delta.astype d = Some "<f4") 151 + | _ -> assert false); 148 152 (* unknown filter *) 149 153 let json = {|{"id":"quantize","digits":10}|} in 150 154 let v = decode f json in 151 155 (match v with 152 - | `Other o -> assert (Zarr_jsont.Other_codec.name o = "quantize") 153 - | _ -> assert false); 156 + | `Other o -> assert (Zarr_jsont.Other_codec.name o = "quantize") 157 + | _ -> assert false); 154 158 print_endline "test_v2_filter: ok" 155 159 156 160 let test_v2_array () = 157 - let json = {|{ 161 + let json = 162 + {|{ 158 163 "zarr_format": 2, 159 164 "shape": [10000, 10000], 160 165 "chunks": [1000, 1000], ··· 163 168 "fill_value": "NaN", 164 169 "order": "C", 165 170 "filters": [{"id": "delta", "dtype": "<f8", "astype": "<f4"}] 166 - }|} in 171 + }|} 172 + in 167 173 let v = decode Zarr_jsont.V2.array_meta_jsont json in 168 - assert (Zarr_jsont.V2.Array_meta.shape v = [10000; 10000]); 169 - assert (Zarr_jsont.V2.Array_meta.chunks v = [1000; 1000]); 174 + assert (Zarr_jsont.V2.Array_meta.shape v = [ 10000; 10000 ]); 175 + assert (Zarr_jsont.V2.Array_meta.chunks v = [ 1000; 1000 ]); 170 176 assert (Zarr_jsont.V2.Array_meta.dtype v = `Float (`Little, 8)); 171 177 assert (Zarr_jsont.V2.Array_meta.order v = `C); 172 178 (match Zarr_jsont.V2.Array_meta.compressor v with 173 - | Some (`Blosc b) -> 174 - assert (Zarr_jsont.V2.Compressor.Blosc.cname b = "lz4") 175 - | _ -> assert false); 179 + | Some (`Blosc b) -> assert (Zarr_jsont.V2.Compressor.Blosc.cname b = "lz4") 180 + | _ -> assert false); 176 181 (match Zarr_jsont.V2.Array_meta.filters v with 177 - | Some [(`Delta _)] -> () 178 - | _ -> assert false); 182 + | Some [ `Delta _ ] -> () 183 + | _ -> assert false); 179 184 (match Zarr_jsont.V2.Array_meta.fill_value v with 180 - | `Float f -> assert (Float.is_nan f) 181 - | _ -> assert false); 185 + | `Float f -> assert (Float.is_nan f) 186 + | _ -> assert false); 182 187 (* roundtrip *) 183 188 let json' = encode Zarr_jsont.V2.array_meta_jsont v in 184 189 let _ = decode Zarr_jsont.V2.array_meta_jsont json' in 185 190 (* null compressor and filters *) 186 - let json2 = {|{ 191 + let json2 = 192 + {|{ 187 193 "zarr_format": 2, 188 194 "shape": [20, 20], 189 195 "chunks": [10, 10], ··· 192 198 "fill_value": 42, 193 199 "order": "C", 194 200 "filters": null 195 - }|} in 201 + }|} 202 + in 196 203 let v2 = decode Zarr_jsont.V2.array_meta_jsont json2 in 197 204 assert (Zarr_jsont.V2.Array_meta.compressor v2 = None); 198 205 assert (Zarr_jsont.V2.Array_meta.filters v2 = None); ··· 203 210 (* bytes *) 204 211 let v = decode c {|{"name":"bytes","configuration":{"endian":"little"}}|} in 205 212 (match v with 206 - | `Bytes b -> assert (Zarr_jsont.V3.Codec.Bytes.endian b = Some `Little) 207 - | _ -> assert false); 213 + | `Bytes b -> assert (Zarr_jsont.V3.Codec.Bytes.endian b = Some `Little) 214 + | _ -> assert false); 208 215 (* gzip *) 209 216 let v = decode c {|{"name":"gzip","configuration":{"level":5}}|} in 210 217 (match v with 211 - | `Gzip g -> assert (Zarr_jsont.V3.Codec.Gzip.level g = 5) 212 - | _ -> assert false); 218 + | `Gzip g -> assert (Zarr_jsont.V3.Codec.Gzip.level g = 5) 219 + | _ -> assert false); 213 220 (* blosc *) 214 - let v = decode c {|{"name":"blosc","configuration":{"cname":"lz4","clevel":5,"shuffle":"shuffle","typesize":4,"blocksize":0}}|} in 221 + let v = 222 + decode c 223 + {|{"name":"blosc","configuration":{"cname":"lz4","clevel":5,"shuffle":"shuffle","typesize":4,"blocksize":0}}|} 224 + in 215 225 (match v with 216 - | `Blosc b -> 217 - assert (Zarr_jsont.V3.Codec.Blosc.cname b = "lz4"); 218 - assert (Zarr_jsont.V3.Codec.Blosc.shuffle b = `Shuffle) 219 - | _ -> assert false); 226 + | `Blosc b -> 227 + assert (Zarr_jsont.V3.Codec.Blosc.cname b = "lz4"); 228 + assert (Zarr_jsont.V3.Codec.Blosc.shuffle b = `Shuffle) 229 + | _ -> assert false); 220 230 (* crc32c *) 221 231 let v = decode c {|{"name":"crc32c"}|} in 222 232 assert (v = `Crc32c); 223 233 (* transpose *) 224 234 let v = decode c {|{"name":"transpose","configuration":{"order":[1,0,2]}}|} in 225 235 (match v with 226 - | `Transpose t -> assert (Zarr_jsont.V3.Codec.Transpose.order t = [1;0;2]) 227 - | _ -> assert false); 236 + | `Transpose t -> assert (Zarr_jsont.V3.Codec.Transpose.order t = [ 1; 0; 2 ]) 237 + | _ -> assert false); 228 238 (* unknown *) 229 239 let v = decode c {|{"name":"zstd","configuration":{"level":3}}|} in 230 240 (match v with 231 - | `Other o -> assert (Zarr_jsont.Other_ext.name o = "zstd") 232 - | _ -> assert false); 241 + | `Other o -> assert (Zarr_jsont.Other_ext.name o = "zstd") 242 + | _ -> assert false); 233 243 (* sharding *) 234 - let v = decode c {|{"name":"sharding_indexed","configuration":{"chunk_shape":[32,32],"codecs":[{"name":"bytes","configuration":{"endian":"little"}}],"index_location":"end"}}|} in 244 + let v = 245 + decode c 246 + {|{"name":"sharding_indexed","configuration":{"chunk_shape":[32,32],"codecs":[{"name":"bytes","configuration":{"endian":"little"}}],"index_location":"end"}}|} 247 + in 235 248 (match v with 236 - | `Sharding s -> 237 - assert (Zarr_jsont.V3.Codec.Sharding.chunk_shape s = [32; 32]); 238 - assert (List.length (Zarr_jsont.V3.Codec.Sharding.codecs s) = 1); 239 - assert (Zarr_jsont.V3.Codec.Sharding.index_location s = `End) 240 - | _ -> assert false); 249 + | `Sharding s -> 250 + assert (Zarr_jsont.V3.Codec.Sharding.chunk_shape s = [ 32; 32 ]); 251 + assert (List.length (Zarr_jsont.V3.Codec.Sharding.codecs s) = 1); 252 + assert (Zarr_jsont.V3.Codec.Sharding.index_location s = `End) 253 + | _ -> assert false); 241 254 print_endline "test_v3_codecs: ok" 242 255 243 256 let test_v3_data_type () = ··· 248 261 assert (decode dt {|"r16"|} = `Raw 16); 249 262 let v = decode dt {|{"name":"datetime","configuration":{"unit":"ns"}}|} in 250 263 (match v with 251 - | `Other o -> assert (Zarr_jsont.Other_ext.name o = "datetime") 252 - | _ -> assert false); 264 + | `Other o -> assert (Zarr_jsont.Other_ext.name o = "datetime") 265 + | _ -> assert false); 253 266 print_endline "test_v3_data_type: ok" 254 267 255 268 let test_v3_array_meta () = 256 - let json = {|{ 269 + let json = 270 + {|{ 257 271 "zarr_format": 3, 258 272 "node_type": "array", 259 273 "shape": [10000, 1000], ··· 264 278 "codecs": [{"name": "bytes", "configuration": {"endian": "little"}}], 265 279 "fill_value": "NaN", 266 280 "attributes": {"foo": 42} 267 - }|} in 281 + }|} 282 + in 268 283 let v = decode Zarr_jsont.V3.array_meta_jsont json in 269 - assert (Zarr_jsont.V3.Array_meta.shape v = [10000; 1000]); 284 + assert (Zarr_jsont.V3.Array_meta.shape v = [ 10000; 1000 ]); 270 285 assert (Zarr_jsont.V3.Array_meta.data_type v = `Float64); 271 - assert (Zarr_jsont.V3.Array_meta.dimension_names v = Some [Some "rows"; Some "columns"]); 286 + assert ( 287 + Zarr_jsont.V3.Array_meta.dimension_names v 288 + = Some [ Some "rows"; Some "columns" ]); 272 289 (match Zarr_jsont.V3.Array_meta.chunk_grid v with 273 - | `Regular r -> assert (Zarr_jsont.V3.Chunk_grid.Regular.chunk_shape r = [1000; 100]) 274 - | _ -> assert false); 290 + | `Regular r -> 291 + assert (Zarr_jsont.V3.Chunk_grid.Regular.chunk_shape r = [ 1000; 100 ]) 292 + | _ -> assert false); 275 293 (match Zarr_jsont.V3.Array_meta.chunk_key_encoding v with 276 - | `Default d -> assert (Zarr_jsont.V3.Chunk_key_encoding.Default.separator d = `Slash) 277 - | _ -> assert false); 294 + | `Default d -> 295 + assert (Zarr_jsont.V3.Chunk_key_encoding.Default.separator d = `Slash) 296 + | _ -> assert false); 278 297 print_endline "test_v3_array_meta: ok" 279 298 280 299 let test_conv_proj () = ··· 286 305 print_endline "test_conv_proj: ok" 287 306 288 307 let test_conv_spatial () = 289 - let json = {|{ 308 + let json = 309 + {|{ 290 310 "spatial:dimensions": ["Y", "X"], 291 311 "spatial:bbox": [-180.0, -90.0, 180.0, 90.0], 292 312 "spatial:transform": [1.0, 0.0, 0.0, 0.0, -1.0, 90.0], 293 313 "spatial:registration": "pixel" 294 - }|} in 314 + }|} 315 + in 295 316 let v = decode Zarr_jsont.Conv.Spatial.jsont json in 296 - assert (Zarr_jsont.Conv.Spatial.dimensions v = ["Y"; "X"]); 317 + assert (Zarr_jsont.Conv.Spatial.dimensions v = [ "Y"; "X" ]); 297 318 assert (Zarr_jsont.Conv.Spatial.registration v = Some `Pixel); 298 - assert (Zarr_jsont.Conv.Spatial.bbox v = Some [-180.0; -90.0; 180.0; 90.0]); 319 + assert (Zarr_jsont.Conv.Spatial.bbox v = Some [ -180.0; -90.0; 180.0; 90.0 ]); 299 320 print_endline "test_conv_spatial: ok" 300 321 301 322 let test_conv_multiscales () = 302 - let json = {|{ 323 + let json = 324 + {|{ 303 325 "layout": [ 304 326 {"asset": "0", "transform": {"scale": [1.0, 1.0]}}, 305 327 {"asset": "1", "derived_from": "0", "transform": {"scale": [2.0, 2.0]}, "resampling_method": "average"} 306 328 ], 307 329 "resampling_method": "average" 308 - }|} in 330 + }|} 331 + in 309 332 let v = decode Zarr_jsont.Conv.Multiscales.jsont json in 310 333 let layout = Zarr_jsont.Conv.Multiscales.layout v in 311 334 assert (List.length layout = 2); ··· 314 337 assert (Zarr_jsont.Conv.Multiscales.Layout_item.derived_from item0 = None); 315 338 let item1 = List.nth layout 1 in 316 339 assert (Zarr_jsont.Conv.Multiscales.Layout_item.derived_from item1 = Some "0"); 317 - assert (Zarr_jsont.Conv.Multiscales.Layout_item.resampling_method item1 = Some "average"); 340 + assert ( 341 + Zarr_jsont.Conv.Multiscales.Layout_item.resampling_method item1 342 + = Some "average"); 318 343 print_endline "test_conv_multiscales: ok" 319 344 320 345 let test_attrs () = 321 - let json = {|{ 346 + let json = 347 + {|{ 322 348 "zarr_conventions": [ 323 349 {"uuid": "f17cb550-5864-4468-aeb7-f3180cfb622f", "name": "proj:", "description": "CRS info"} 324 350 ], ··· 326 352 "spatial:dimensions": ["Y", "X"], 327 353 "spatial:transform": [10.0, 0.0, 0.0, 0.0, -10.0, 100.0], 328 354 "custom_key": "custom_value" 329 - }|} in 355 + }|} 356 + in 330 357 let v = decode Zarr_jsont.attrs_jsont json in 331 358 (match Zarr_jsont.Attrs.proj v with 332 - | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:3857") 333 - | None -> assert false); 359 + | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:3857") 360 + | None -> assert false); 334 361 (match Zarr_jsont.Attrs.spatial v with 335 - | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = ["Y"; "X"]) 336 - | None -> assert false); 362 + | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = [ "Y"; "X" ]) 363 + | None -> assert false); 337 364 assert (Zarr_jsont.Attrs.multiscales v = None); 338 365 assert (List.length (Zarr_jsont.Attrs.conventions v) >= 1); 339 366 (* roundtrip *) 340 367 let json' = encode Zarr_jsont.attrs_jsont v in 341 368 let v' = decode Zarr_jsont.attrs_jsont json' in 342 369 (match Zarr_jsont.Attrs.proj v' with 343 - | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:3857") 344 - | None -> assert false); 370 + | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:3857") 371 + | None -> assert false); 345 372 (match Zarr_jsont.Attrs.spatial v' with 346 - | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = ["Y"; "X"]) 347 - | None -> assert false); 373 + | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = [ "Y"; "X" ]) 374 + | None -> assert false); 348 375 (* empty attrs *) 349 376 let e = Zarr_jsont.Attrs.empty in 350 377 assert (Zarr_jsont.Attrs.conventions e = []); ··· 354 381 print_endline "test_attrs: ok" 355 382 356 383 let test_v2_node_array () = 357 - let json = {|{ 384 + let json = 385 + {|{ 358 386 "zarr_format": 2, 359 387 "shape": [100, 100], 360 388 "chunks": [10, 10], ··· 363 391 "fill_value": 42, 364 392 "order": "C", 365 393 "filters": null 366 - }|} in 394 + }|} 395 + in 367 396 let v = decode Zarr_jsont.v2_array_jsont json in 368 397 (match Zarr_jsont.V2_node.kind v with 369 - | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [100; 100]) 370 - | `Group -> assert false); 398 + | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [ 100; 100 ]) 399 + | `Group -> assert false); 371 400 assert (Zarr_jsont.Attrs.proj (Zarr_jsont.V2_node.attrs v) = None); 372 401 (* roundtrip *) 373 402 let json' = encode Zarr_jsont.v2_array_jsont v in 374 403 let v' = decode Zarr_jsont.v2_array_jsont json' in 375 404 (match Zarr_jsont.V2_node.kind v' with 376 - | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [100; 100]) 377 - | `Group -> assert false); 405 + | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [ 100; 100 ]) 406 + | `Group -> assert false); 378 407 print_endline "test_v2_node_array: ok" 379 408 380 409 let test_v2_group () = ··· 389 418 print_endline "test_v2_group: ok" 390 419 391 420 let test_v3_node_group () = 392 - let json = {|{ 421 + let json = 422 + {|{ 393 423 "zarr_format": 3, 394 424 "node_type": "group", 395 425 "attributes": { 396 426 "proj:code": "EPSG:4326", 397 427 "spatial:dimensions": ["Y", "X"] 398 428 } 399 - }|} in 429 + }|} 430 + in 400 431 let v = decode Zarr_jsont.v3_jsont json in 401 432 assert (Zarr_jsont.V3_node.kind v = `Group); 402 433 (match Zarr_jsont.Attrs.proj (Zarr_jsont.V3_node.attrs v) with 403 - | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 404 - | None -> assert false); 434 + | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 435 + | None -> assert false); 405 436 (match Zarr_jsont.Attrs.spatial (Zarr_jsont.V3_node.attrs v) with 406 - | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = ["Y"; "X"]) 407 - | None -> assert false); 437 + | Some s -> assert (Zarr_jsont.Conv.Spatial.dimensions s = [ "Y"; "X" ]) 438 + | None -> assert false); 408 439 (* roundtrip *) 409 440 let json' = encode Zarr_jsont.v3_jsont v in 410 441 let v' = decode Zarr_jsont.v3_jsont json' in 411 442 assert (Zarr_jsont.V3_node.kind v' = `Group); 412 443 (match Zarr_jsont.Attrs.proj (Zarr_jsont.V3_node.attrs v') with 413 - | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 414 - | None -> assert false); 444 + | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 445 + | None -> assert false); 415 446 print_endline "test_v3_node_group: ok" 416 447 417 448 let test_v3_node_array () = 418 - let json = {|{ 449 + let json = 450 + {|{ 419 451 "zarr_format": 3, 420 452 "node_type": "array", 421 453 "shape": [100], ··· 424 456 "chunk_key_encoding": {"name": "default", "configuration": {"separator": "/"}}, 425 457 "codecs": [{"name": "bytes", "configuration": {"endian": "little"}}], 426 458 "fill_value": 0 427 - }|} in 459 + }|} 460 + in 428 461 let v = decode Zarr_jsont.v3_jsont json in 429 462 (match Zarr_jsont.V3_node.kind v with 430 - | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [100]) 431 - | `Group -> assert false); 463 + | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [ 100 ]) 464 + | `Group -> assert false); 432 465 assert (Zarr_jsont.Attrs.proj (Zarr_jsont.V3_node.attrs v) = None); 433 466 (* roundtrip *) 434 467 let json' = encode Zarr_jsont.v3_jsont v in 435 468 let v' = decode Zarr_jsont.v3_jsont json' in 436 469 (match Zarr_jsont.V3_node.kind v' with 437 - | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [100]) 438 - | `Group -> assert false); 470 + | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [ 100 ]) 471 + | `Group -> assert false); 439 472 print_endline "test_v3_node_array: ok" 440 473 441 474 let test_v3_node_array_with_attrs () = 442 - let json = {|{ 475 + let json = 476 + {|{ 443 477 "zarr_format": 3, 444 478 "node_type": "array", 445 479 "shape": [50, 50], ··· 451 485 "attributes": { 452 486 "proj:code": "EPSG:4326" 453 487 } 454 - }|} in 488 + }|} 489 + in 455 490 let v = decode Zarr_jsont.v3_jsont json in 456 491 (match Zarr_jsont.V3_node.kind v with 457 - | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [50; 50]) 458 - | `Group -> assert false); 492 + | `Array a -> assert (Zarr_jsont.V3.Array_meta.shape a = [ 50; 50 ]) 493 + | `Group -> assert false); 459 494 (match Zarr_jsont.Attrs.proj (Zarr_jsont.V3_node.attrs v) with 460 - | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 461 - | None -> assert false); 495 + | Some p -> assert (Zarr_jsont.Conv.Proj.code p = Some "EPSG:4326") 496 + | None -> assert false); 462 497 print_endline "test_v3_node_array_with_attrs: ok" 463 498 464 499 let test_dispatch_v2_array () = 465 - let json = {|{ 500 + let json = 501 + {|{ 466 502 "zarr_format": 2, 467 503 "shape": [20, 20], 468 504 "chunks": [10, 10], ··· 471 507 "fill_value": 42, 472 508 "order": "C", 473 509 "filters": null 474 - }|} in 510 + }|} 511 + in 475 512 let v = decode Zarr_jsont.jsont json in 476 513 (match v with 477 - | `V2 node -> 478 - (match Zarr_jsont.V2_node.kind node with 479 - | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [20; 20]) 514 + | `V2 node -> ( 515 + match Zarr_jsont.V2_node.kind node with 516 + | `Array a -> assert (Zarr_jsont.V2.Array_meta.shape a = [ 20; 20 ]) 480 517 | `Group -> assert false) 481 - | `V3 _ -> assert false); 518 + | `V3 _ -> assert false); 482 519 print_endline "test_dispatch_v2_array: ok" 483 520 484 521 let test_dispatch_v2_group () = 485 522 let json = {|{"zarr_format": 2}|} in 486 523 let v = decode Zarr_jsont.jsont json in 487 524 (match v with 488 - | `V2 node -> assert (Zarr_jsont.V2_node.kind node = `Group) 489 - | `V3 _ -> assert false); 525 + | `V2 node -> assert (Zarr_jsont.V2_node.kind node = `Group) 526 + | `V3 _ -> assert false); 490 527 print_endline "test_dispatch_v2_group: ok" 491 528 492 529 let test_dispatch_v3_array () = 493 - let json = {|{ 530 + let json = 531 + {|{ 494 532 "zarr_format": 3, 495 533 "node_type": "array", 496 534 "shape": [100], ··· 499 537 "chunk_key_encoding": {"name": "default", "configuration": {"separator": "/"}}, 500 538 "codecs": [{"name": "bytes", "configuration": {"endian": "little"}}], 501 539 "fill_value": 0 502 - }|} in 540 + }|} 541 + in 503 542 let v = decode Zarr_jsont.jsont json in 504 543 (match v with 505 - | `V3 node -> 506 - (match Zarr_jsont.V3_node.kind node with 544 + | `V3 node -> ( 545 + match Zarr_jsont.V3_node.kind node with 507 546 | `Array a -> assert (Zarr_jsont.V3.Array_meta.data_type a = `Int32) 508 547 | `Group -> assert false) 509 - | `V2 _ -> assert false); 548 + | `V2 _ -> assert false); 510 549 print_endline "test_dispatch_v3_array: ok" 511 550 512 551 let test_dispatch_v3_group () = 513 552 let json = {|{"zarr_format": 3, "node_type": "group"}|} in 514 553 let v = decode Zarr_jsont.jsont json in 515 554 (match v with 516 - | `V3 node -> assert (Zarr_jsont.V3_node.kind node = `Group) 517 - | `V2 _ -> assert false); 555 + | `V3 node -> assert (Zarr_jsont.V3_node.kind node = `Group) 556 + | `V2 _ -> assert false); 518 557 print_endline "test_dispatch_v3_group: ok" 519 558 520 559 let () = test_other_codec () ··· 547 586 let v = decode Zarr_jsont.v3_jsont json_str in 548 587 let json' = encode Zarr_jsont.v3_jsont v in 549 588 let v' = decode Zarr_jsont.v3_jsont json' in 550 - (match Zarr_jsont.V3_node.kind v, Zarr_jsont.V3_node.kind v' with 551 - | `Array a, `Array a' -> 552 - assert (Zarr_jsont.V3.Array_meta.shape a = Zarr_jsont.V3.Array_meta.shape a'); 553 - assert (Zarr_jsont.V3.Array_meta.data_type a = Zarr_jsont.V3.Array_meta.data_type a') 554 - | `Group, `Group -> () 555 - | _ -> assert false) 589 + match (Zarr_jsont.V3_node.kind v, Zarr_jsont.V3_node.kind v') with 590 + | `Array a, `Array a' -> 591 + assert ( 592 + Zarr_jsont.V3.Array_meta.shape a = Zarr_jsont.V3.Array_meta.shape a'); 593 + assert ( 594 + Zarr_jsont.V3.Array_meta.data_type a 595 + = Zarr_jsont.V3.Array_meta.data_type a') 596 + | `Group, `Group -> () 597 + | _ -> assert false 556 598 557 599 let test_roundtrip_v3_array () = 558 - roundtrip_v3 {|{ 600 + roundtrip_v3 601 + {|{ 559 602 "zarr_format": 3, 560 603 "node_type": "array", 561 604 "shape": [10000, 1000], ··· 570 613 print_endline "test_roundtrip_v3_array: ok" 571 614 572 615 let test_roundtrip_v3_group_with_convs () = 573 - roundtrip_v3 {|{ 616 + roundtrip_v3 617 + {|{ 574 618 "zarr_format": 3, 575 619 "node_type": "group", 576 620 "attributes": { ··· 586 630 print_endline "test_roundtrip_v3_group_with_convs: ok" 587 631 588 632 let test_roundtrip_v2 () = 589 - let json = {|{ 633 + let json = 634 + {|{ 590 635 "zarr_format": 2, 591 636 "shape": [10000, 10000], 592 637 "chunks": [1000, 1000], ··· 595 640 "fill_value": "NaN", 596 641 "order": "C", 597 642 "filters": [{"id": "delta", "dtype": "<f8", "astype": "<f4"}] 598 - }|} in 643 + }|} 644 + in 599 645 let v = decode Zarr_jsont.v2_array_jsont json in 600 646 let json' = encode Zarr_jsont.v2_array_jsont v in 601 647 let v' = decode Zarr_jsont.v2_array_jsont json' in 602 - let get_shape n = match Zarr_jsont.V2_node.kind n with 648 + let get_shape n = 649 + match Zarr_jsont.V2_node.kind n with 603 650 | `Array a -> Zarr_jsont.V2.Array_meta.shape a 604 651 | `Group -> failwith "expected array" 605 652 in ··· 607 654 print_endline "test_roundtrip_v2: ok" 608 655 609 656 let test_roundtrip_multiscales () = 610 - roundtrip_v3 {|{ 657 + roundtrip_v3 658 + {|{ 611 659 "zarr_format": 3, 612 660 "node_type": "group", 613 661 "attributes": { ··· 633 681 634 682 let test_unknown_preservation () = 635 683 (* V2 array with extra unknown field *) 636 - let json = {|{ 684 + let json = 685 + {|{ 637 686 "zarr_format": 2, 638 687 "shape": [10], 639 688 "chunks": [5], ··· 643 692 "order": "C", 644 693 "filters": null, 645 694 "custom_extension": {"nested": true} 646 - }|} in 695 + }|} 696 + in 647 697 let v = decode Zarr_jsont.v2_array_jsont json in 648 698 let json' = encode Zarr_jsont.v2_array_jsont v in 649 699 let v' = decode Zarr_jsont.v2_array_jsont json' in 650 700 (match Zarr_jsont.V2_node.kind v' with 651 - | `Array a -> 652 - let unk = Zarr_jsont.V2.Array_meta.unknown a in 653 - (match unk with 701 + | `Array a -> ( 702 + let unk = Zarr_jsont.V2.Array_meta.unknown a in 703 + match unk with 654 704 | Jsont.Object (mems, _) -> 655 - assert (List.exists (fun ((k, _), _) -> k = "custom_extension") mems) 705 + assert (List.exists (fun ((k, _), _) -> k = "custom_extension") mems) 656 706 | _ -> assert false) 657 - | _ -> assert false); 707 + | _ -> assert false); 658 708 659 709 (* V2 compressor with extra unknown fields *) 660 - let json = {|{"id":"blosc","cname":"lz4","clevel":5,"shuffle":1,"extra_param":"test"}|} in 710 + let json = 711 + {|{"id":"blosc","cname":"lz4","clevel":5,"shuffle":1,"extra_param":"test"}|} 712 + in 661 713 let v = decode Zarr_jsont.V2.compressor_jsont json in 662 714 let json' = encode Zarr_jsont.V2.compressor_jsont v in 663 715 let v' = decode Zarr_jsont.V2.compressor_jsont json' in 664 716 (match v' with 665 - | `Blosc b -> 666 - let unk = Zarr_jsont.V2.Compressor.Blosc.unknown b in 667 - (match unk with 717 + | `Blosc b -> ( 718 + let unk = Zarr_jsont.V2.Compressor.Blosc.unknown b in 719 + match unk with 668 720 | Jsont.Object (mems, _) -> 669 - assert (List.exists (fun ((k, _), _) -> k = "extra_param") mems) 721 + assert (List.exists (fun ((k, _), _) -> k = "extra_param") mems) 670 722 | _ -> assert false) 671 - | _ -> assert false); 723 + | _ -> assert false); 672 724 673 725 (* Attrs with unknown custom key *) 674 726 let json = {|{"custom_key": "custom_value", "another": 42}|} in ··· 677 729 let v' = decode Zarr_jsont.attrs_jsont json' in 678 730 let unk = Zarr_jsont.Attrs.unknown v' in 679 731 (match unk with 680 - | Jsont.Object (mems, _) -> 681 - assert (List.exists (fun ((k, _), _) -> k = "custom_key") mems); 682 - assert (List.exists (fun ((k, _), _) -> k = "another") mems) 683 - | _ -> assert false); 732 + | Jsont.Object (mems, _) -> 733 + assert (List.exists (fun ((k, _), _) -> k = "custom_key") mems); 734 + assert (List.exists (fun ((k, _), _) -> k = "another") mems) 735 + | _ -> assert false); 684 736 print_endline "test_unknown_preservation: ok" 685 737 686 738 let () = test_unknown_preservation ()