Skip to content

Commit 7d0b71c

Browse files
committed
Add support for storage transformers.
1 parent aa31327 commit 7d0b71c

File tree

8 files changed

+143
-25
lines changed

8 files changed

+143
-25
lines changed

lib/extensions.ml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,88 @@ module Datatype = struct
187187
| `String "nativeint" -> Ok Nativeint
188188
| _ -> Error ("Unsupported metadata data_type")
189189
end
190+
191+
type tf_error =
192+
[ `Store_read of string
193+
| `Store_write of string ]
194+
195+
module type STF = sig
196+
type t
197+
val get : t -> string -> (string, [> tf_error]) result
198+
val set : t -> string -> string -> unit
199+
val erase : t -> string -> unit
200+
end
201+
202+
module StorageTransformers = struct
203+
type transformer =
204+
| Identity
205+
type t = transformer list
206+
207+
let default = [Identity]
208+
209+
let deserialize x =
210+
match
211+
Util.get_name x,
212+
Yojson.Safe.Util.(member "configuration" x)
213+
with
214+
| "identity", `Null -> Ok Identity
215+
| _ ->
216+
Error "Unsupported storage transformer name or configuration."
217+
218+
let of_yojson x =
219+
let open Util.Result_syntax in
220+
List.fold_right
221+
(fun x acc ->
222+
acc >>= fun l ->
223+
deserialize x >>| fun s ->
224+
s :: l) (Yojson.Safe.Util.to_list x) (Ok [])
225+
226+
let to_yojson x =
227+
`List
228+
(List.fold_right
229+
(fun x acc ->
230+
match x with
231+
| Identity -> acc) x [])
232+
233+
let get
234+
(type a)
235+
(module M : STF with type t = a)
236+
(store : a)
237+
(transformers : t)
238+
(key : string)
239+
=
240+
let open Util.Result_syntax in
241+
M.get store key >>| fun raw ->
242+
snd @@
243+
List.fold_right
244+
(fun x (k, v) ->
245+
match x with
246+
| Identity -> (k, v)) transformers (key, raw)
247+
248+
let set
249+
(type a)
250+
(module M : STF with type t = a)
251+
(store : a)
252+
(transformers : t)
253+
(key : string)
254+
(value : string)
255+
=
256+
let k', v' =
257+
List.fold_left
258+
(fun (k, v) -> function
259+
| Identity -> (k, v)) (key, value) transformers
260+
in
261+
M.set store k' v'
262+
263+
let erase
264+
(type a)
265+
(module M : STF with type t = a)
266+
(store : a)
267+
(transformers : t)
268+
(key : string)
269+
=
270+
M.erase store @@
271+
List.fold_left
272+
(fun k -> function
273+
| Identity -> k) key transformers
274+
end

lib/extensions.mli

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,30 @@ module Datatype : sig
4646
val of_yojson : Yojson.Safe.t -> (t, string) result
4747
val to_yojson : t -> Yojson.Safe.t
4848
end
49+
50+
type tf_error =
51+
[ `Store_read of string
52+
| `Store_write of string ]
53+
54+
module type STF = sig
55+
type t
56+
val get : t -> string -> (string, [> tf_error]) result
57+
val set : t -> string -> string -> unit
58+
val erase : t -> string -> unit
59+
end
60+
61+
module StorageTransformers : sig
62+
type transformer =
63+
| Identity
64+
type t = transformer list
65+
66+
val default : t
67+
val get :
68+
(module STF with type t = 'a) -> 'a -> t -> string -> (string, [> tf_error ]) result
69+
val set :
70+
(module STF with type t = 'a) -> 'a -> t -> string -> string -> unit
71+
val erase :
72+
(module STF with type t = 'a) -> 'a -> t -> string -> unit
73+
val to_yojson : t -> Yojson.Safe.t
74+
val of_yojson : Yojson.Safe.t -> (t, string) result
75+
end

lib/metadata.ml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,14 @@ module ArrayMetadata = struct
112112
;chunk_key_encoding : ChunkKeyEncoding.t
113113
;attributes : Yojson.Safe.t
114114
;dimension_names : string option list
115-
;storage_transformers : Yojson.Safe.t Util.ExtPoint.t list}
115+
;storage_transformers : StorageTransformers.t}
116116

117117
let create
118118
?(sep=`Slash)
119119
?(codecs=Codecs.Chain.default)
120120
?(dimension_names=[])
121121
?(attributes=`Null)
122+
?(storage_transformers=[StorageTransformers.Identity])
122123
~shape
123124
kind
124125
fv
@@ -134,7 +135,7 @@ module ArrayMetadata = struct
134135
;dimension_names
135136
;zarr_format = 3
136137
;node_type = "array"
137-
;storage_transformers = []
138+
;storage_transformers
138139
;fill_value = FillValue.of_kind kind fv
139140
;data_type = Datatype.of_kind kind
140141
;chunk_key_encoding = ChunkKeyEncoding.create sep}
@@ -168,6 +169,12 @@ module ArrayMetadata = struct
168169
| None -> `Null) xs
169170
in
170171
l @ [("dimension_names", `List xs')]
172+
in
173+
let l =
174+
match t.storage_transformers with
175+
| [] | [StorageTransformers.Identity] -> l
176+
| xs ->
177+
l @ [("storage_transformers", StorageTransformers.to_yojson xs)]
171178
in `Assoc l
172179

173180
let of_yojson x =
@@ -256,8 +263,10 @@ module ArrayMetadata = struct
256263
>>= fun dimension_names ->
257264

258265
(match member "storage_transformers" x with
259-
| `Null -> Ok []
260-
| _ -> Error "storage_transformers field is not yet supported.")
266+
| `Null | `List [] ->
267+
Ok StorageTransformers.default
268+
| _ ->
269+
Error "storage_transformers field is not yet supported.")
261270
>>| fun storage_transformers ->
262271

263272
{zarr_format; shape; node_type; data_type; codecs; fill_value; chunk_grid
@@ -286,6 +295,8 @@ module ArrayMetadata = struct
286295

287296
let attributes t = t.attributes
288297

298+
let storage_transformers t = t.storage_transformers
299+
289300
let chunk_shape t =
290301
RegularGrid.chunk_shape t.chunk_grid
291302

lib/metadata.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ module ArrayMetadata : sig
3838
?codecs:Codecs.Chain.t ->
3939
?dimension_names:string option list ->
4040
?attributes:Yojson.Safe.t ->
41+
?storage_transformers:Extensions.StorageTransformers.t ->
4142
shape:int array ->
4243
('a, 'b) Bigarray.kind ->
4344
'a ->
@@ -76,6 +77,10 @@ module ArrayMetadata : sig
7677
(** [attributes t] Returns a Yojson type containing user attributes assigned
7778
to the zarr array represented by [t]. *)
7879

80+
val storage_transformers : t -> Extensions.StorageTransformers.t
81+
(** [storage_transformers t] Returns the storage transformers to be applied
82+
to the keys and values of this store. *)
83+
7984
val dimension_names : t -> string option list
8085
(** [dimension_name t] returns a list of dimension names. If none are
8186
defined then an empty list is returned. *)

lib/storage/storage.ml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module ArraySet = Util.ArraySet
88
module Arraytbl = Util.Arraytbl
99
module AM = Metadata.ArrayMetadata
1010
module GM = Metadata.GroupMetadata
11+
module ST = Extensions.StorageTransformers
1112

1213
module Make (M : STORE) : S with type t = M.t = struct
1314
include M
@@ -35,6 +36,7 @@ module Make (M : STORE) : S with type t = M.t = struct
3536
?(sep=`Slash)
3637
?(dimension_names=[])
3738
?(attributes=`Null)
39+
?(storage_transformers=[])
3840
?codecs
3941
~shape
4042
~chunks
@@ -54,6 +56,7 @@ module Make (M : STORE) : S with type t = M.t = struct
5456
~codecs
5557
~dimension_names
5658
~attributes
59+
~storage_transformers
5760
~shape
5861
kind
5962
fill_value
@@ -154,11 +157,12 @@ module Make (M : STORE) : S with type t = M.t = struct
154157
in
155158
let codecs = AM.codecs meta in
156159
let prefix = ArrayNode.to_key node ^ "/" in
160+
let tf = AM.storage_transformers meta in
157161
let cindices = ArraySet.of_seq @@ Arraytbl.to_seq_keys tbl in
158162
ArraySet.fold (fun idx acc ->
159163
acc >>= fun () ->
160164
let chunkkey = prefix ^ AM.chunk_key meta idx in
161-
(match get t chunkkey with
165+
(match ST.get (module M) t tf chunkkey with
162166
| Ok b ->
163167
Codecs.Chain.decode codecs repr b
164168
| Error _ ->
@@ -173,7 +177,7 @@ module Make (M : STORE) : S with type t = M.t = struct
173177
List.iter
174178
(fun (c, v) -> Ndarray.set arr c v) @@ Arraytbl.find_all tbl idx;
175179
Codecs.Chain.encode codecs arr >>| fun encoded ->
176-
set t chunkkey encoded) cindices (Ok ())
180+
ST.set (module M) t tf chunkkey encoded) cindices (Ok ())
177181

178182
let get_array
179183
: type a b.
@@ -206,6 +210,7 @@ module Make (M : STORE) : S with type t = M.t = struct
206210
let tbl = Arraytbl.create @@ Array.length pair in
207211
let prefix = ArrayNode.to_key node ^ "/" in
208212
let chain = AM.codecs meta in
213+
let tf = AM.storage_transformers meta in
209214
let repr =
210215
{kind
211216
;shape = AM.chunk_shape meta
@@ -217,7 +222,7 @@ module Make (M : STORE) : S with type t = M.t = struct
217222
| Some arr ->
218223
Ok (Ndarray.get arr coord :: l)
219224
| None ->
220-
(match get t @@ prefix ^ AM.chunk_key meta idx with
225+
(match ST.get (module M) t tf @@ prefix ^ AM.chunk_key meta idx with
221226
| Ok b ->
222227
Codecs.Chain.decode chain repr b
223228
| Error _ ->
@@ -243,8 +248,9 @@ module Make (M : STORE) : S with type t = M.t = struct
243248
ArraySet.of_list @@ AM.chunk_indices meta @@ AM.shape meta in
244249
let s' =
245250
ArraySet.of_list @@ AM.chunk_indices meta shape in
251+
let tf = AM.storage_transformers meta in
246252
ArraySet.iter
247-
(fun v -> erase t @@ pre ^ AM.chunk_key meta v)
253+
(fun v -> ST.erase (module M) t tf @@ pre ^ AM.chunk_key meta v)
248254
ArraySet.(diff s s');
249255
Ok (set t mkey @@ AM.encode @@ AM.update_shape meta shape)
250256
end

lib/storage/storage_intf.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ module type S = sig
5656
: ?sep:[< `Dot | `Slash > `Slash ] ->
5757
?dimension_names:string option list ->
5858
?attributes:Yojson.Safe.t ->
59+
?storage_transformers:Extensions.StorageTransformers.t ->
5960
?codecs:Codecs.chain ->
6061
shape:int array ->
6162
chunks:int array ->

lib/util.ml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
module ExtPoint = struct
2-
type 'a t =
3-
{name : string
4-
;configuration : 'a}
5-
6-
let ( = ) cmp x y =
7-
(x.name = y.name) &&
8-
cmp x.configuration y.configuration
9-
end
10-
111
type ('a, 'b) array_repr =
122
{kind : ('a, 'b) Bigarray.kind
133
;shape : int array

lib/util.mli

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@ type ('a, 'b) array_repr =
55
(** The type summarizing the decoded/encoded representation of a Zarr array
66
or chunk. *)
77

8-
module ExtPoint : sig
9-
(** The type representing a JSON extension point metadata configuration. *)
10-
11-
type 'a t = {name : string ; configuration : 'a}
12-
val ( = ) : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
13-
end
14-
158
module StrMap : sig include Hashtbl.S with type key = string end
169
(** A hashtable with string keys. *)
1710

0 commit comments

Comments
 (0)