@@ -18,9 +18,9 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator};
1818use rayon_iter_concurrent_limit:: iter_concurrent_limit;
1919use unsafe_cell_slice:: UnsafeCellSlice ;
2020use utils:: is_whole_chunk;
21+ use zarrs:: array:: codec:: ArrayBytesDecodeIntoTarget ;
2122use zarrs:: array:: codec:: {
22- ArrayBytesDecodeIntoTarget , ArrayPartialDecoderTraits , ArrayToBytesCodecTraits , CodecOptions ,
23- StoragePartialDecoder ,
23+ ArrayPartialDecoderTraits , ArrayToBytesCodecTraits , CodecOptions , StoragePartialDecoder ,
2424} ;
2525use zarrs:: array:: {
2626 ArrayBytes , ArrayBytesFixedDisjointView , ArrayMetadata , CodecChain , DataType , DataTypeExt ,
@@ -70,13 +70,13 @@ impl CodecPipelineImpl {
7070 codec_chain : & CodecChain ,
7171 codec_options : & CodecOptions ,
7272 ) -> PyResult < ArrayBytes < ' a > > {
73- let value_encoded = self . store . get ( & item. key ) . map_py_err :: < PyRuntimeError > ( ) ?;
73+ let value_encoded = self . store . get ( item. key ( ) ) . map_py_err :: < PyRuntimeError > ( ) ?;
7474 let value_decoded = if let Some ( value_encoded) = value_encoded {
7575 let value_encoded: Vec < u8 > = value_encoded. into ( ) ; // zero-copy in this case
7676 codec_chain
7777 . decode (
7878 value_encoded. into ( ) ,
79- & item. chunk_shape ,
79+ item. shape ( ) ,
8080 & self . data_type ,
8181 & self . fill_value ,
8282 codec_options,
@@ -101,12 +101,12 @@ impl CodecPipelineImpl {
101101 . map_codec_err ( ) ?;
102102
103103 if value_decoded. is_fill_value ( & self . fill_value ) {
104- self . store . erase ( & item. key ) . map_py_err :: < PyRuntimeError > ( )
104+ self . store . erase ( item. key ( ) ) . map_py_err :: < PyRuntimeError > ( )
105105 } else {
106106 let value_encoded = codec_chain
107107 . encode (
108108 value_decoded,
109- & item. chunk_shape ,
109+ item. shape ( ) ,
110110 & self . data_type ,
111111 & self . fill_value ,
112112 codec_options,
@@ -116,7 +116,7 @@ impl CodecPipelineImpl {
116116
117117 // Store the encoded chunk
118118 self . store
119- . set ( & item. key , value_encoded. into ( ) )
119+ . set ( item. key ( ) , value_encoded. into ( ) )
120120 . map_py_err :: < PyRuntimeError > ( )
121121 }
122122 }
@@ -129,20 +129,17 @@ impl CodecPipelineImpl {
129129 chunk_subset : & ArraySubset ,
130130 codec_options : & CodecOptions ,
131131 ) -> PyResult < ( ) > {
132- let chunk_shape = item
133- . chunk_shape
134- . clone ( )
135- . into_iter ( )
136- . map ( |v| u64:: from ( v) )
137- . collect :: < Vec < u64 > > ( ) ;
138- if !chunk_subset. inbounds_shape ( & chunk_shape) {
132+ let array_shape = item. shape ( ) ;
133+ if !chunk_subset. inbounds_shape ( bytemuck:: must_cast_slice ( array_shape) ) {
139134 return Err ( PyErr :: new :: < PyValueError , _ > ( format ! (
140- "chunk subset ({chunk_subset}) is out of bounds for array shape ({chunk_shape :?})"
135+ "chunk subset ({chunk_subset}) is out of bounds for array shape ({array_shape :?})"
141136 ) ) ) ;
142137 }
143138 let data_type_size = self . data_type . size ( ) ;
144139
145- if chunk_subset. start ( ) . iter ( ) . all ( |& o| o == 0 ) && chunk_subset. shape ( ) == chunk_shape {
140+ if chunk_subset. start ( ) . iter ( ) . all ( |& o| o == 0 )
141+ && chunk_subset. shape ( ) == bytemuck:: must_cast_slice :: < _ , u64 > ( array_shape)
142+ {
146143 // Fast path if the chunk subset spans the entire chunk, no read required
147144 self . store_chunk_bytes ( item, codec_chain, chunk_subset_bytes, codec_options)
148145 } else {
@@ -157,7 +154,7 @@ impl CodecPipelineImpl {
157154 // Update the chunk
158155 let chunk_bytes_new = update_array_bytes (
159156 chunk_bytes_old,
160- & chunk_shape ,
157+ bytemuck :: must_cast_slice ( array_shape ) ,
161158 chunk_subset,
162159 & chunk_subset_bytes,
163160 data_type_size,
@@ -251,12 +248,10 @@ impl CodecPipelineImpl {
251248 let codec_metadata = metadata. codecs ;
252249 let codec_chain =
253250 Arc :: new ( CodecChain :: from_metadata ( & codec_metadata) . map_py_err :: < PyTypeError > ( ) ?) ;
254- let mut codec_options = CodecOptions :: default ( ) ;
251+ let codec_options = CodecOptions :: default ( ) . with_validate_checksums ( validate_checksums ) ;
255252
256- codec_options. set_validate_checksums ( validate_checksums) ;
257-
258- let chunk_concurrent_minimum = chunk_concurrent_minimum
259- . unwrap_or ( zarrs:: config:: global_config ( ) . chunk_concurrent_minimum ( ) ) ;
253+ let chunk_concurrent_minimum =
254+ chunk_concurrent_minimum. unwrap_or ( global_config ( ) . chunk_concurrent_minimum ( ) ) ;
260255 let chunk_concurrent_maximum =
261256 chunk_concurrent_maximum. unwrap_or ( rayon:: current_num_threads ( ) ) ;
262257 let num_threads = num_threads. unwrap_or ( rayon:: current_num_threads ( ) ) ;
@@ -302,7 +297,7 @@ impl CodecPipelineImpl {
302297 let partial_chunk_descriptions_with_representations = chunk_descriptions
303298 . iter ( )
304299 . filter ( |item| !( is_whole_chunk ( item) ) )
305- . unique_by ( |item| item. key . clone ( ) )
300+ . unique_by ( |item| item. key ( ) . clone ( ) )
306301 . collect :: < Vec < _ > > ( ) ;
307302 let mut partial_decoder_cache: HashMap < StoreKey , Arc < dyn ArrayPartialDecoderTraits > > =
308303 HashMap :: new ( ) ;
@@ -313,19 +308,20 @@ impl CodecPipelineImpl {
313308 map,
314309 |item| {
315310 let storage_handle = Arc :: new( StorageHandle :: new( self . store. clone( ) ) ) ;
316- let input_handle = StoragePartialDecoder :: new( storage_handle, item. key. clone( ) ) ;
311+ let input_handle =
312+ StoragePartialDecoder :: new( storage_handle, item. key( ) . clone( ) ) ;
317313 let partial_decoder = self
318314 . codec_chain
319315 . clone( )
320316 . partial_decoder(
321317 Arc :: new( input_handle) ,
322- & item. chunk_shape ,
318+ item. shape ( ) ,
323319 & self . data_type,
324320 & self . fill_value,
325321 & codec_options,
326322 )
327323 . map_codec_err( ) ?;
328- Ok ( ( item. key. clone( ) , partial_decoder) )
324+ Ok ( ( item. key( ) . clone( ) , partial_decoder) )
329325 }
330326 )
331327 . collect :: < PyResult < Vec < _ > > > ( ) ?;
@@ -336,14 +332,8 @@ impl CodecPipelineImpl {
336332 // FIXME: the `decode_into` methods only support fixed length data types.
337333 // For variable length data types, need a codepath with non `_into` methods.
338334 // Collect all the subsets and copy into value on the Python side?
339- let update_chunk_subset = |item| {
340- let chunk_item:: WithSubset {
341- key,
342- subset,
343- chunk_subset,
344- chunk_shape_u64,
345- ..
346- } = item;
335+ let update_chunk_subset = |item : WithSubset | {
336+ let shape = item. shape ( ) ;
347337 let mut output_view = unsafe {
348338 // TODO: Is the following correct?
349339 // can we guarantee that when this function is called from Python with arbitrary arguments?
@@ -356,24 +346,24 @@ impl CodecPipelineImpl {
356346 . ok_or ( "variable length data type not supported" )
357347 . map_py_err :: < PyTypeError > ( ) ?,
358348 & output_shape,
359- subset,
349+ item . subset . clone ( ) ,
360350 )
361351 . map_py_err :: < PyRuntimeError > ( ) ?
362352 } ;
363353 let target = ArrayBytesDecodeIntoTarget :: Fixed ( & mut output_view) ;
364354 // See zarrs::array::Array::retrieve_chunk_subset_into
365- if chunk_subset. start ( ) . iter ( ) . all ( |& o| o == 0 )
366- && chunk_subset. shape ( ) == chunk_shape_u64
355+ if item . chunk_subset . start ( ) . iter ( ) . all ( |& o| o == 0 )
356+ && item . chunk_subset . shape ( ) == bytemuck :: must_cast_slice :: < _ , u64 > ( shape )
367357 {
368358 // See zarrs::array::Array::retrieve_chunk_into
369359 if let Some ( chunk_encoded) =
370- self . store . get ( & key) . map_py_err :: < PyRuntimeError > ( ) ?
360+ self . store . get ( item . key ( ) ) . map_py_err :: < PyRuntimeError > ( ) ?
371361 {
372362 // Decode the encoded data into the output buffer
373363 let chunk_encoded: Vec < u8 > = chunk_encoded. into ( ) ;
374364 self . codec_chain . decode_into (
375365 Cow :: Owned ( chunk_encoded) ,
376- & item. chunk_shape ,
366+ item. shape ( ) ,
377367 & self . data_type ,
378368 & self . fill_value ,
379369 target,
@@ -384,11 +374,11 @@ impl CodecPipelineImpl {
384374 copy_fill_value_into ( & self . data_type , & self . fill_value , target)
385375 }
386376 } else {
387- let key = & key;
377+ let key = item . key ( ) ;
388378 let partial_decoder = partial_decoder_cache. get ( key) . ok_or_else ( || {
389379 PyRuntimeError :: new_err ( format ! ( "Partial decoder not found for key: {key}" ) )
390380 } ) ?;
391- partial_decoder. partial_decode_into ( & chunk_subset, target, & codec_options)
381+ partial_decoder. partial_decode_into ( & item . chunk_subset , target, & codec_options)
392382 }
393383 . map_codec_err ( )
394384 } ;
0 commit comments