diff --git a/README.md b/README.md index 8198dc4..87d6075 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,7 @@ let config = ;b2b = [Crc32c]} ;index_location = Start};; let codec_chain = - {a2a = [] - ;a2b = ShardingIndexed config - ;b2b = [Crc32c]};; + {a2a = []; a2b = ShardingIndexed config; b2b = []};; let shard_node = Result.get_ok @@ ArrayNode.(group_node / "another");; @@ -124,7 +122,6 @@ FilesystemStore.array_exists store shard_node;; FilesystemStore.group_exists store group_node;; let a, g = - Result.get_ok @@ FilesystemStore.find_child_nodes store group_node;; List.map ArrayNode.to_path a;; (*- : string list = ["/some/group/name"; "/some/group/another"] *) diff --git a/dune-project b/dune-project index 3f69e7e..3cee859 100644 --- a/dune-project +++ b/dune-project @@ -23,15 +23,15 @@ dune (ocaml (>= 4.14.2)) yojson - ppx_deriving_yojson + ppx_deriving ezgzip - checkseum + owl stdint + checkseum (ounit2 :with-test) (odoc :with-doc) (bisect_ppx - (and :dev (>= 2.5.0) :with-test)) - owl) + (and :dev (>= 2.5.0) :with-test))) (tags (topics "to describe" your project))) diff --git a/lib/codecs/array_to_array.ml b/lib/codecs/array_to_array.ml index e929f46..8de6b96 100644 --- a/lib/codecs/array_to_array.ml +++ b/lib/codecs/array_to_array.ml @@ -7,7 +7,7 @@ type array_to_array = [@@deriving show] type error = - [ `Invalid_transpose_order of dimension_order * string ] + [ `Transpose_order of dimension_order * string ] (* https://zarr-specs.readthedocs.io/en/latest/v3/codecs/transpose/v1.0.html *) module TransposeCodec = struct @@ -26,7 +26,7 @@ module TransposeCodec = struct let msg = "transpose order leads to a change in encoded representation size, which is prohibited." in - Result.error @@ `Invalid_transpose_order (t, msg) + Result.error @@ `Transpose_order (t, msg) else Ok {decoded with shape} with @@ -34,13 +34,13 @@ module TransposeCodec = struct let msg = "transpose order max element is larger than the decoded representation dimensionality." in - Result.error @@ `Invalid_transpose_order (t, msg) + Result.error @@ `Transpose_order (t, msg) let parse_order o = if Array.length o = 0 then let msg = "transpose order cannot be empty." in - Result.error @@ `Invalid_transpose_order (o, msg) + Result.error @@ `Transpose_order (o, msg) else let o' = Array.copy o in Array.fast_sort Int.compare o'; @@ -48,7 +48,7 @@ module TransposeCodec = struct let msg = "order must not have any repeated dimensions or negative values." in - Result.error @@ `Invalid_transpose_order (o, msg) + Result.error @@ `Transpose_order (o, msg) else Result.ok @@ Transpose o @@ -64,18 +64,18 @@ module TransposeCodec = struct let msg = "Transpose order must have the same length as the decoded representation's number of dims." in - Result.error @@ `Invalid_transpose_order (o, msg) + Result.error @@ `Transpose_order (o, msg) else if not @@ Array.for_all (fun x -> x <= max) o then let msg = "Largest value of transpose order must not be larger than then dimensionality of the decoded representation." in - Result.error @@ `Invalid_transpose_order (o, msg) + Result.error @@ `Transpose_order (o, msg) else Ok () let encode o x = try Ok (Ndarray.transpose ~axis:o x) with - | Failure s -> Error (`Invalid_transpose_order (o, s)) + | Failure s -> Error (`Transpose_order (o, s)) let decode o x = let inv_order = Array.(make (length o) 0) in diff --git a/lib/codecs/array_to_array.mli b/lib/codecs/array_to_array.mli index 599909a..fcdb587 100644 --- a/lib/codecs/array_to_array.mli +++ b/lib/codecs/array_to_array.mli @@ -6,7 +6,7 @@ type array_to_array = | Transpose of dimension_order type error = - [ `Invalid_transpose_order of dimension_order * string ] + [ `Transpose_order of dimension_order * string ] val pp_array_to_array : Format.formatter -> array_to_array -> unit val show_array_to_array : array_to_array -> string diff --git a/lib/codecs/array_to_bytes.ml b/lib/codecs/array_to_bytes.ml index 0782e6c..a71261f 100644 --- a/lib/codecs/array_to_bytes.ml +++ b/lib/codecs/array_to_bytes.ml @@ -32,12 +32,10 @@ and chain = [@@deriving show] type error = - [ `Bytes_encode_error of string - | `Bytes_decode_error of string - | `Sharding_shape_mismatch of int array * int array * string - | Extensions.error + [ Extensions.error | Array_to_array.error - | Bytes_to_bytes.error ] + | Bytes_to_bytes.error + | `Sharding of int array * int array * string ] (* https://zarr-specs.readthedocs.io/en/latest/v3/codecs/bytes/v1.0.html *) module BytesCodec = struct @@ -205,6 +203,15 @@ end = struct type t = shard_config + let parse_chain repr chain = + List.fold_left + (fun acc c -> + acc >>= fun r -> + ArrayToArray.parse r c >>= fun () -> + ArrayToArray.compute_encoded_representation c r) (Ok repr) chain.a2a + >>= fun repr' -> + ArrayToBytes.parse repr' chain.a2b + let parse : type a b. (a, b) Util.array_repr -> @@ -217,10 +224,9 @@ end = struct let msg = "sharding chunk_shape length must equal the dimensionality of the decoded representaton of a shard." in - Result.error @@ - `Sharding_shape_mismatch (t.chunk_shape, repr.shape, msg)) + Result.error @@ `Sharding (t.chunk_shape, repr.shape, msg)) >>= fun () -> - match + (match Array.for_all2 (fun x y -> (x mod y) = 0) repr.shape t.chunk_shape with | true -> Ok () @@ -228,8 +234,10 @@ end = struct let msg = "sharding chunk_shape must evenly divide the size of the shard shape." in - Result.error @@ - `Sharding_shape_mismatch (t.chunk_shape, repr.shape, msg) + Result.error @@ `Sharding (t.chunk_shape, repr.shape, msg)) + >>= fun () -> + parse_chain repr t.codecs >>= fun () -> + parse_chain repr t.index_codecs let compute_encoded_size input_size t = List.fold_left BytesToBytes.compute_encoded_size diff --git a/lib/codecs/array_to_bytes.mli b/lib/codecs/array_to_bytes.mli index 1596483..8a85458 100644 --- a/lib/codecs/array_to_bytes.mli +++ b/lib/codecs/array_to_bytes.mli @@ -27,9 +27,7 @@ type error = [ Extensions.error | Array_to_array.error | Bytes_to_bytes.error - | `Bytes_encode_error of string - | `Bytes_decode_error of string - | `Sharding_shape_mismatch of int array * int array * string ] + | `Sharding of int array * int array * string ] module ArrayToBytes : sig val parse diff --git a/lib/extensions.ml b/lib/extensions.ml index 3b0cb25..1606e44 100644 --- a/lib/extensions.ml +++ b/lib/extensions.ml @@ -1,10 +1,5 @@ -type grid_info = - {msg : string - ;chunk_shape : int array - ;array_shape : int array} - type error = - [ `Grid of grid_info ] + [ `Extension of string ] module RegularGrid = struct type t = int array @@ -15,10 +10,10 @@ module RegularGrid = struct match chunk_shape, array_shape with | c, a when Array.(length c <> length a) -> let msg = "grid chunk and array shape must have the same the length." in - Result.error @@ `Grid {msg; array_shape; chunk_shape} + Result.error @@ `Extension msg | c, a when Util.(max c > max a) -> let msg = "grid chunk dimension size must not be larger than array's." in - Result.error @@ `Grid {msg; array_shape; chunk_shape} + Result.error @@ `Extension msg | c, _ -> Ok c let ceildiv x y = diff --git a/lib/extensions.mli b/lib/extensions.mli index 2ac37d1..78a62ef 100644 --- a/lib/extensions.mli +++ b/lib/extensions.mli @@ -1,10 +1,5 @@ -type grid_info = - {msg : string - ;chunk_shape : int array - ;array_shape : int array} - type error = - [ `Grid of grid_info ] + [ `Extension of string ] module RegularGrid : sig type t diff --git a/lib/metadata.ml b/lib/metadata.ml index 27fbb71..c3638bf 100644 --- a/lib/metadata.ml +++ b/lib/metadata.ml @@ -2,8 +2,7 @@ open Extensions open Util.Result_syntax type error = - [ Extensions.error - | `Json_decode of string ] + [ `Metadata of string ] module FillValue = struct type t = @@ -126,6 +125,7 @@ module ArrayMetadata = struct chunks = RegularGrid.create ~array_shape:shape chunks + >>? (fun (`Extension msg) -> `Metadata msg) >>| fun chunk_grid -> {shape ;codecs @@ -223,7 +223,7 @@ module ArrayMetadata = struct | xs -> RegularGrid.of_yojson xs >>= fun grid -> RegularGrid.(create ~array_shape:shape @@ chunk_shape grid) - >>? fun (`Grid {msg; _}) -> msg) + >>? fun (`Extension msg) -> msg) >>= fun chunk_grid -> (match member "chunk_key_encoding" x with @@ -305,8 +305,7 @@ module ArrayMetadata = struct Yojson.Safe.to_string @@ to_yojson t let decode b = - of_yojson @@ Yojson.Safe.from_string b >>? fun s -> - `Json_decode s + of_yojson @@ Yojson.Safe.from_string b let update_attributes t attrs = {t with attributes = attrs} @@ -404,8 +403,7 @@ module GroupMetadata = struct Ok {zarr_format; node_type; attributes} let decode s = - of_yojson @@ Yojson.Safe.from_string s >>? fun b -> - `Json_decode b + of_yojson @@ Yojson.Safe.from_string s let encode t = Yojson.Safe.to_string @@ to_yojson t diff --git a/lib/metadata.mli b/lib/metadata.mli index 926b73f..203854d 100644 --- a/lib/metadata.mli +++ b/lib/metadata.mli @@ -6,9 +6,8 @@ [zarr.json] within the prefix of a group or array.*) type error = - [ Extensions.error - | `Json_decode of string ] -(** A type for JSON decoding errors. *) + [ `Metadata of string ] +(** A type for Metadata operation errors. *) module FillValue : sig type t = @@ -51,7 +50,7 @@ module ArrayMetadata : sig val encode : t -> string (** [encode t] returns a byte string representing a JSON Zarr array metadata. *) - val decode : string -> (t, [> error ]) result + val decode : string -> (t, string) result (** [decode s] decodes a bytes string [s] into a {!ArrayMetadata.t} type, and returns an error if the decoding process fails. *) @@ -135,7 +134,7 @@ module GroupMetadata : sig val encode : t -> string (** [encode t] returns a byte string representing a JSON Zarr group metadata. *) - val decode : string -> (t, [> error ]) result + val decode : string -> (t, string) result (** [decode s] decodes a bytes string [s] into a {!t} type, and returns an error if the decoding process fails. *) diff --git a/lib/node.ml b/lib/node.ml index a0cd8b1..0069010 100644 --- a/lib/node.ml +++ b/lib/node.ml @@ -12,7 +12,6 @@ module GroupNode = struct type t = | Root | Cons of t * string - [@@deriving show] let create parent name = if rep_ok name then @@ -87,14 +86,16 @@ module GroupNode = struct | _, Root -> false | v, Cons (parent, _) -> parent = v - let show n = to_path n + let show = to_path + + let pp fmt t = + Format.fprintf fmt "%s" @@ show t end module ArrayNode = struct type t = {parent : GroupNode.t ;name : string} - [@@deriving show] let create parent name = if rep_ok name then @@ -145,4 +146,7 @@ module ArrayNode = struct let to_metakey p = to_key p ^ "/zarr.json" let show = to_path + + let pp fmt t = + Format.fprintf fmt "%s" @@ show t end diff --git a/lib/storage/memory.ml b/lib/storage/memory.ml index d68ad93..c0afff1 100644 --- a/lib/storage/memory.ml +++ b/lib/storage/memory.ml @@ -1,10 +1,4 @@ -module HashableString = struct - type t = string - let hash = Hashtbl.hash - let equal = String.equal -end - -module StrMap = Hashtbl.Make (HashableString) +module StrMap = Util.StrMap let create () = StrMap.create 16 @@ -13,7 +7,8 @@ module Impl = struct let get t key = Option.to_result - ~none:(`Store_read key) @@ StrMap.find_opt t key + ~none:(`Store_read (key ^ " not found.")) @@ + StrMap.find_opt t key let set t key value = StrMap.replace t key value diff --git a/lib/storage/storage.ml b/lib/storage/storage.ml index 4dd8cdd..e6274e0 100644 --- a/lib/storage/storage.ml +++ b/lib/storage/storage.ml @@ -65,20 +65,12 @@ module Make (M : STORE) : S with type t = M.t = struct Some (ArrayNode.parent node) let group_metadata node t = - if not @@ group_exists t node then - Result.error @@ - `Store_read (GroupNode.show node ^ " is not a member of this store.") - else - get t @@ GroupNode.to_metakey node >>= fun bytes -> - GM.decode bytes + get t @@ GroupNode.to_metakey node >>= fun bytes -> + GM.decode bytes >>? fun msg -> `Store_read msg let array_metadata node t = - if not @@ array_exists t node then - Result.error @@ - `Store_read (ArrayNode.show node ^ " is not a member of this store.") - else - get t @@ ArrayNode.to_metakey node >>= fun bytes -> - AM.decode bytes + get t @@ ArrayNode.to_metakey node >>= fun bytes -> + AM.decode bytes >>? fun msg -> `Store_read msg (* Assumes without checking that [metakey] is a valid node metadata key.*) let unsafe_node_type t metakey = @@ -87,22 +79,16 @@ module Make (M : STORE) : S with type t = M.t = struct |> Util.member "node_type" |> Util.to_string let find_child_nodes t node = - if group_exists t node then - Result.ok @@ - List.fold_left - (fun (lacc, racc) pre -> - let p = "/" ^ String.(length pre - 1 |> sub pre 0) in - if unsafe_node_type t (pre ^ "zarr.json") = "array" then - let x = Result.get_ok @@ ArrayNode.of_path p in - x :: lacc, racc - else - let x = Result.get_ok @@ GroupNode.of_path p in - lacc, x :: racc) - ([], []) (snd @@ list_dir t @@ GroupNode.to_prefix node) - else - let msg = - GroupNode.show node ^ " is not a node in this heirarchy." in - Result.error @@ `Store_read msg + List.fold_left + (fun (lacc, racc) pre -> + let p = "/" ^ String.(length pre - 1 |> sub pre 0) in + if unsafe_node_type t (pre ^ "zarr.json") = "array" then + let x = Result.get_ok @@ ArrayNode.of_path p in + x :: lacc, racc + else + let x = Result.get_ok @@ GroupNode.of_path p in + lacc, x :: racc) + ([], []) (snd @@ list_dir t @@ GroupNode.to_prefix node) let find_all_nodes t = let keys = @@ -138,11 +124,11 @@ module Make (M : STORE) : S with type t = M.t = struct Owl_types.index array -> (a, b) Ndarray.t -> t -> - (unit, [> error]) result + (unit, [> error ]) result = fun node slice x t -> let open Util in get t @@ ArrayNode.to_metakey node >>= fun bytes -> - AM.decode bytes >>= fun meta -> + AM.decode bytes >>? (fun msg -> `Store_write msg) >>= fun meta -> (if Ndarray.shape x = Indexing.slice_shape slice @@ AM.shape meta then Ok () else @@ -199,7 +185,7 @@ module Make (M : STORE) : S with type t = M.t = struct = fun node slice kind t -> let open Util in get t @@ ArrayNode.to_metakey node >>= fun bytes -> - AM.decode bytes >>= fun meta -> + AM.decode bytes >>? (fun msg -> `Store_read msg) >>= fun meta -> (if AM.is_valid_kind meta kind then Ok () else @@ -245,7 +231,8 @@ module Make (M : STORE) : S with type t = M.t = struct let reshape t node shape = let mkey = ArrayNode.to_metakey node in get t mkey >>= fun bytes -> - AM.decode bytes >>= fun meta -> + AM.decode bytes >>? (fun msg -> `Store_write msg) + >>= fun meta -> (if Array.length shape = Array.length @@ AM.shape meta then Ok () else diff --git a/lib/storage/storage_intf.ml b/lib/storage/storage_intf.ml index f880fec..0017f1d 100644 --- a/lib/storage/storage_intf.ml +++ b/lib/storage/storage_intf.ml @@ -7,10 +7,7 @@ type range = ByteRange of int * int option type error = [ `Store_read of string - | `Store_write of string - | Node.error - | Metadata.error - | Codecs.error ] + | `Store_write of string ] module type STORE = sig (** The abstract STORE interface that stores should implement. @@ -31,7 +28,7 @@ module type STORE = sig type t val get : t -> key -> (string, [> error]) result - val get_partial_values : t -> (key * range) list -> string option list + val get_partial_values : t -> (key * range) list -> (string list, [> error ]) result val set : t -> key -> string -> unit val set_partial_values : t -> (key * int * string) list -> (unit, [> error]) result val erase : t -> key -> unit @@ -66,7 +63,7 @@ module type S = sig 'a -> ArrayNode.t -> t -> - (unit, [> error ]) result + (unit, [> Codecs.error | Extensions.error | Metadata.error ]) result (** [create_array ~sep ~dimension_names ~attributes ~codecs ~shape ~chunks kind fill node t] creates an array node in store [t] where: - Separator [sep] is used in the array's chunk key encoding. @@ -79,19 +76,20 @@ module type S = sig This operation can fail if the codec chain is not well defined. *) val array_metadata - : ArrayNode.t -> t -> (ArrayMetadata.t, [> error]) result + : ArrayNode.t -> t -> (ArrayMetadata.t, [> error ]) result (** [array_metadata node t] returns the metadata of array node [node]. This operation returns an error if node is not a member of store [t]. *) val group_metadata - : GroupNode.t -> t -> (GroupMetadata.t, [> error]) result + : GroupNode.t -> t -> (GroupMetadata.t, [> error ]) result (** [group_metadata node t] returns the metadata of group node [node]. This operation returns an error if node is not a member of store [t].*) val find_child_nodes - : t -> GroupNode.t -> (ArrayNode.t list * GroupNode.t list, [> error]) result + : t -> GroupNode.t -> ArrayNode.t list * GroupNode.t list (** [find_child_nodes t n] returns a tuple of child nodes of group node [n]. - This operation can fail if [n] is not a member of store [t]. *) + This operation returns a pair of empty lists if node [n] has no + children or is not a member of store [t]. *) val find_all_nodes : t -> ArrayNode.t list * GroupNode.t list (** [find_all_nodes t] returns [Some p] where [p] is a pair of lists @@ -126,7 +124,7 @@ module type S = sig Owl_types.index array -> ('a, 'b) Ndarray.t -> t -> - (unit, [> error]) result + (unit, [> error | Node.error | Codecs.error ]) result (** [set_array n s x t] writes n-dimensional array [x] to the slice [s] of array node [n] in store [t]. This operation fails if: - the ndarray [x] size does not equal slice [s]. @@ -139,7 +137,7 @@ module type S = sig Owl_types.index array -> ('a, 'b) Bigarray.kind -> t -> - (('a, 'b) Ndarray.t, [> error]) result + (('a, 'b) Ndarray.t, [> error | Node.error | Codecs.error ]) result (** [get_array n s k t] reads an n-dimensional array of size determined by slice [s] from array node [n]. This operation fails if: - If there is a problem decoding/encoding node [n] chunks. @@ -217,39 +215,29 @@ module Base = struct in StrSet.(elements keys, elements prefixes) - let rec get_partial_values ~get_fn t kr_pairs = - match kr_pairs with - | [] -> [None] - | (k, r) :: xs -> - match get_fn t k with - | Error _ -> - None :: (get_partial_values ~get_fn t xs) - | Ok v -> - try - let sub = match r with - | ByteRange (rs, None) -> - String.sub v rs @@ String.length v - | ByteRange (rs, Some rl) -> - String.sub v rs rl in - Some sub :: (get_partial_values ~get_fn t xs) - with - | Invalid_argument _ -> - None :: (get_partial_values ~get_fn t xs) - - let rec set_partial_values ~set_fn ~get_fn t = function - | [] -> Ok () - | (k, rs, v) :: xs -> - match get_fn t k with - | Error _ -> - set_fn t k v; - set_partial_values ~set_fn ~get_fn t xs - | Ok ov -> - try - let ov' = Bytes.of_string ov in - String.(length v |> blit v 0 ov' rs); - set_fn t k @@ Bytes.to_string ov'; - set_partial_values ~set_fn ~get_fn t xs - with - | Invalid_argument s -> - Error (`Store_read s) + let get_partial_values ~get_fn t kr_pairs = + let open Util.Result_syntax in + List.fold_right + (fun (k, ByteRange (rs, len)) acc -> + acc >>= fun xs -> + get_fn t k >>| fun v -> + (match len with + | None -> String.sub v rs @@ String.length v - rs + | Some l -> String.sub v rs l) :: xs) kr_pairs (Ok []) + + let set_partial_values ~set_fn ~get_fn t krv = + let open Util.Result_syntax in + let module StrMap = Util.StrMap in + let tbl = StrMap.create @@ List.length krv in + List.fold_right + (fun (k, rs, v) acc -> + acc >>= fun () -> + (match StrMap.find_opt tbl k with + | None -> + get_fn t k + | Some ov -> Ok ov) + >>| fun ov -> + let ov' = Bytes.of_string ov in + String.(length v |> blit v 0 ov' rs); + set_fn t k @@ Bytes.to_string ov') krv (Ok ()) end diff --git a/lib/util.ml b/lib/util.ml index 78656cb..616cd07 100644 --- a/lib/util.ml +++ b/lib/util.ml @@ -24,10 +24,18 @@ module ComparableArray = struct let compare = Stdlib.compare end +module HashableString = struct + type t = string + let hash = Hashtbl.hash + let equal = String.equal +end + module ArraySet = Set.Make (ComparableArray) module Arraytbl = Hashtbl.Make (HashableArray) +module StrMap = Hashtbl.Make (HashableString) + module Result_syntax = struct let ( >>= ) = Result.bind diff --git a/lib/util.mli b/lib/util.mli index 1960a15..3deea05 100644 --- a/lib/util.mli +++ b/lib/util.mli @@ -12,6 +12,9 @@ module ExtPoint : sig val ( = ) : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool end +module StrMap : sig include Hashtbl.S with type key = string end +(** A hashtable with string keys. *) + module Arraytbl : sig include Hashtbl.S with type key = int array end (** A hashtable with integer array keys. *) diff --git a/test/test_node.ml b/test/test_node.ml index c39d38f..9b620dc 100644 --- a/test/test_node.ml +++ b/test/test_node.ml @@ -129,7 +129,7 @@ let array_node = [ let s = "/some/dir/moredirs/path/pname" in let n = ArrayNode.of_path s |> Result.get_ok in assert_equal "pname" @@ ArrayNode.name n; - assert_equal ~printer:Fun.id s @@ ArrayNode.to_path n; + assert_equal ~printer:Fun.id s @@ ArrayNode.show n; (* parent tests *) assert_equal @@ -138,8 +138,10 @@ let array_node = [ ArrayNode.parent (ArrayNode.of_path "/nodename" |> Result.get_ok); (* equality tests *) + let n' = (ArrayNode.of_path s |> Result.get_ok) in assert_equal - true @@ ArrayNode.(n = (ArrayNode.of_path s |> Result.get_ok)); + ~printer:ArrayNode.show n n'; + assert_equal true ArrayNode.(n = n'); assert_equal false @@ ArrayNode.(n = Result.get_ok @@ ArrayNode.of_path (s ^ "/more")); diff --git a/test/test_storage.ml b/test/test_storage.ml index 30f1794..2ae9697 100644 --- a/test/test_storage.ml +++ b/test/test_storage.ml @@ -133,7 +133,7 @@ let test_store let child = GroupNode.of_path "/some/child" |> Result.get_ok in M.create_group store child; (match M.find_child_nodes store gnode with - | Ok (arrays, groups) -> + | arrays, groups -> assert_equal ~printer:string_of_list ["/arrnode"] @@ @@ -141,19 +141,11 @@ let test_store assert_equal ~printer:string_of_list ["/some"] @@ - List.map GroupNode.to_path groups - | Error _ -> - assert_failure - "a store with more than one node - should return children for a root node."); + List.map GroupNode.to_path groups); (* test getting child nodes of a group not a member of this store. *) - let r = - M.find_child_nodes store @@ - (Result.get_ok @@ GroupNode.(root / "fakegroup")) in - assert_bool - "finding child nodes of a non-store group node should fail." @@ - Result.is_error r; + let g = (Result.get_ok @@ GroupNode.(root / "fakegroup")) in + assert_equal ([], []) @@ M.find_child_nodes store g; let ac, gc = M.find_all_nodes store in let got = diff --git a/zarr.opam b/zarr.opam index a536498..4735c34 100644 --- a/zarr.opam +++ b/zarr.opam @@ -13,14 +13,14 @@ depends: [ "dune" {>= "3.15"} "ocaml" {>= "4.14.2"} "yojson" - "ppx_deriving_yojson" + "ppx_deriving" "ezgzip" - "checkseum" + "owl" "stdint" + "checkseum" "ounit2" {with-test} "odoc" {with-doc} "bisect_ppx" {dev & >= "2.5.0" & with-test} - "owl" ] build: [ ["dune" "subst"] {dev}