From c72757ec71706e20e3d9af8f1e636b2fb81d4cae Mon Sep 17 00:00:00 2001 From: Lachlan Deakin Date: Sat, 10 Feb 2024 12:38:09 +1100 Subject: [PATCH] Added `Array::retrieve_chunk_if_exists` and variants --- CHANGELOG.md | 1 + src/array.rs | 38 +++++- src/array/array_async_readable.rs | 184 ++++++++++++++++++------------ src/array/array_sync_readable.rs | 169 ++++++++++++++++----------- 4 files changed, 253 insertions(+), 139 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b07851a3..56ebf55c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `{Chunk,Array}Representation::shape_u64` - Added `ChunkGridTraits::chunk_shape_u64` to `ChunkGridTraits` - **Breaking** added `chunk_shape_u64_unchecked` to `ChunkGridTraits` which must be implemented by chunk grids + - Added `Array::retrieve_chunk_if_exists` and variants (`async_`, `_elements`, `_ndarray`) ### Changed - Dependency bumps diff --git a/src/array.rs b/src/array.rs index a886c5c1..f6614067 100644 --- a/src/array.rs +++ b/src/array.rs @@ -674,6 +674,31 @@ fn iter_u64_to_usize<'a, I: Iterator>(iter: I) -> Vec { .collect::>() } +fn validate_element_size(data_type: &DataType) -> Result<(), ArrayError> { + if data_type.size() == std::mem::size_of::() { + Ok(()) + } else { + Err(ArrayError::IncompatibleElementSize( + data_type.size(), + std::mem::size_of::(), + )) + } +} + +#[cfg(feature = "ndarray")] +fn elements_to_ndarray( + shape: &[u64], + elements: Vec, +) -> Result, ArrayError> { + let length = elements.len(); + ndarray::ArrayD::::from_shape_vec(iter_u64_to_usize(shape.iter()), elements).map_err(|_| { + ArrayError::CodecError(codec::CodecError::UnexpectedChunkDecodedSize( + length * std::mem::size_of::(), + shape.iter().product::() * std::mem::size_of::() as u64, + )) + }) +} + #[cfg(test)] mod tests { use itertools::Itertools; @@ -765,7 +790,7 @@ mod tests { array .store_array_subset_elements::( &ArraySubset::new_with_ranges(&[3..6, 3..6]), - vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], + vec![1.0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], ) .unwrap(); @@ -781,13 +806,22 @@ mod tests { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 0 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 1 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 2 - 1.0, 1.0, 1.0, 0.1, 0.2, 0.3, 1.0, 1.0, //_3____________ + 1.0, 1.0, 1.0, 1.0, 0.2, 0.3, 1.0, 1.0, //_3____________ 1.0, 1.0, 1.0, 0.4, 0.5, 0.6, 1.0, 1.0, // 4 1.0, 1.0, 1.0, 0.7, 0.8, 0.9, 1.0, 1.0, // 5 (1, 1) 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 6 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // 7 ] ); + assert!(array + .retrieve_chunk_elements_if_exists::(&[0; 2]) + .unwrap() + .is_none()); + #[cfg(feature = "ndarray")] + assert!(array + .retrieve_chunk_ndarray_if_exists::(&[0; 2]) + .unwrap() + .is_none()); } fn array_subset_locking(locks: StoreLocks, expect_equal: bool) { diff --git a/src/array/array_async_readable.rs b/src/array/array_async_readable.rs index 8adefdf2..edda2cc8 100644 --- a/src/array/array_async_readable.rs +++ b/src/array/array_async_readable.rs @@ -14,51 +14,13 @@ use super::{ ArrayCodecTraits, ArrayToBytesCodecTraits, AsyncArrayPartialDecoderTraits, AsyncStoragePartialDecoder, }, + transmute_from_bytes_vec, unsafe_cell_slice::UnsafeCellSlice, - Array, ArrayCreateError, ArrayError, ArrayMetadata, + validate_element_size, Array, ArrayCreateError, ArrayError, ArrayMetadata, }; -// FIXME: Matches array_retrieve_elements with await -macro_rules! array_async_retrieve_elements { - ( $self:expr, $func:ident($($arg:tt)*) ) => { - if $self.data_type.size() != std::mem::size_of::() { - Err(ArrayError::IncompatibleElementSize( - $self.data_type.size(), - std::mem::size_of::(), - )) - } else { - let bytes = $self.$func($($arg)*).await?; - let elements = crate::array::transmute_from_bytes_vec::(bytes); - Ok(elements) - } - }; -} - -// FIXME: Matches array_retrieve_ndarray with await #[cfg(feature = "ndarray")] -macro_rules! array_async_retrieve_ndarray { - ( $self:expr, $shape:expr, $func:ident($($arg:tt)*) ) => { - if $self.data_type.size() != std::mem::size_of::() { - Err(ArrayError::IncompatibleElementSize( - $self.data_type.size(), - std::mem::size_of::(), - )) - } else { - let elements = $self.$func($($arg)*).await?; - let length = elements.len(); - ndarray::ArrayD::::from_shape_vec( - super::iter_u64_to_usize($shape.iter()), - elements, - ) - .map_err(|_| { - ArrayError::CodecError(crate::array::codec::CodecError::UnexpectedChunkDecodedSize( - length * std::mem::size_of::(), - $shape.iter().product::() * std::mem::size_of::() as u64, - )) - }) - } - }; -} +use super::elements_to_ndarray; impl Array { /// Create an array in `storage` at `path`. The metadata is read from the store. @@ -78,7 +40,7 @@ impl Array { Self::new_with_metadata(storage, path, metadata) } - /// Read and decode the chunk at `chunk_indices` into its bytes. + /// Read and decode the chunk at `chunk_indices` into its bytes if it exists. /// /// # Errors /// Returns an [`ArrayError`] if @@ -88,7 +50,10 @@ impl Array { /// /// # Panics /// Panics if the number of elements in the chunk exceeds `usize::MAX`. - pub async fn async_retrieve_chunk(&self, chunk_indices: &[u64]) -> Result, ArrayError> { + pub async fn async_retrieve_chunk_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { let storage_handle = Arc::new(StorageHandle::new(&*self.storage)); let storage_transformer = self .storage_transformers() @@ -101,8 +66,8 @@ impl Array { ) .await .map_err(ArrayError::StorageError)?; - let chunk_representation = self.chunk_array_representation(chunk_indices)?; if let Some(chunk_encoded) = chunk_encoded { + let chunk_representation = self.chunk_array_representation(chunk_indices)?; let chunk_decoded = self .codecs() .async_decode_opt(chunk_encoded, &chunk_representation, self.parallel_codecs()) @@ -111,7 +76,7 @@ impl Array { let chunk_decoded_size = chunk_representation.num_elements_usize() * chunk_representation.data_type().size(); if chunk_decoded.len() == chunk_decoded_size { - Ok(chunk_decoded) + Ok(Some(chunk_decoded)) } else { Err(ArrayError::UnexpectedChunkDecodedSize( chunk_decoded.len(), @@ -119,12 +84,50 @@ impl Array { )) } } else { + Ok(None) + } + } + + /// Read and decode the chunk at `chunk_indices` into its bytes or the fill value if it does not exist. + /// + /// # Errors + /// Returns an [`ArrayError`] if + /// - `chunk_indices` are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + /// + /// # Panics + /// Panics if the number of elements in the chunk exceeds `usize::MAX`. + pub async fn async_retrieve_chunk(&self, chunk_indices: &[u64]) -> Result, ArrayError> { + let chunk = self.async_retrieve_chunk_if_exists(chunk_indices).await?; + if let Some(chunk) = chunk { + Ok(chunk) + } else { + let chunk_representation = self.chunk_array_representation(chunk_indices)?; let fill_value = chunk_representation.fill_value().as_ne_bytes(); Ok(fill_value.repeat(chunk_representation.num_elements_usize())) } } - /// Read and decode the chunk at `chunk_indices` into a vector of its elements. + /// Read and decode the chunk at `chunk_indices` into a vector of its elements if it exists. + /// + /// # Errors + /// Returns an [`ArrayError`] if + /// - the size of `T` does not match the data type size, + /// - the decoded bytes cannot be transmuted, + /// - `chunk_indices` are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + pub async fn async_retrieve_chunk_elements_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { + validate_element_size::(self.data_type())?; + let bytes = self.async_retrieve_chunk_if_exists(chunk_indices).await?; + Ok(bytes.map(|bytes| transmute_from_bytes_vec::(bytes))) + } + + /// Read and decode the chunk at `chunk_indices` into a vector of its elements or the fill value if it does not exist. /// /// # Errors /// Returns an [`ArrayError`] if @@ -137,11 +140,45 @@ impl Array { &self, chunk_indices: &[u64], ) -> Result, ArrayError> { - array_async_retrieve_elements!(self, async_retrieve_chunk(chunk_indices)) + validate_element_size::(self.data_type())?; + let bytes = self.async_retrieve_chunk(chunk_indices).await?; + Ok(transmute_from_bytes_vec::(bytes)) } #[cfg(feature = "ndarray")] - /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`]. + /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`] if it exists. + /// + /// # Errors + /// Returns an [`ArrayError`] if: + /// - the size of `T` does not match the data type size, + /// - the decoded bytes cannot be transmuted, + /// - the chunk indices are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + /// + /// # Panics + /// Will panic if a chunk dimension is larger than `usize::MAX`. + pub async fn async_retrieve_chunk_ndarray_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { + // validate_element_size::(self.data_type())?; in // async_retrieve_chunk_elements_if_exists + let shape = self + .chunk_grid() + .chunk_shape_u64(chunk_indices, self.shape())? + .ok_or_else(|| ArrayError::InvalidChunkGridIndicesError(chunk_indices.to_vec()))?; + let elements = self + .async_retrieve_chunk_elements_if_exists(chunk_indices) + .await?; + if let Some(elements) = elements { + Ok(Some(elements_to_ndarray(&shape, elements)?)) + } else { + Ok(None) + } + } + + #[cfg(feature = "ndarray")] + /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`]. It is filled with the fill value if it does not exist. /// /// # Errors /// Returns an [`ArrayError`] if: @@ -157,11 +194,13 @@ impl Array { &self, chunk_indices: &[u64], ) -> Result, ArrayError> { - let shape = &self + // validate_element_size::(self.data_type())?; // in async_retrieve_chunk_elements + let shape = self .chunk_grid() .chunk_shape_u64(chunk_indices, self.shape())? .ok_or_else(|| ArrayError::InvalidChunkGridIndicesError(chunk_indices.to_vec()))?; - array_async_retrieve_ndarray!(self, shape, async_retrieve_chunk_elements(chunk_indices)) + let elements = self.async_retrieve_chunk_elements(chunk_indices).await?; + elements_to_ndarray(&shape, elements) } /// Read and decode the chunk at `chunk_indices` into its bytes. @@ -231,7 +270,9 @@ impl Array { &self, chunks: &ArraySubset, ) -> Result, ArrayError> { - array_async_retrieve_elements!(self, async_retrieve_chunks(chunks)) + validate_element_size::(self.data_type())?; + let bytes = self.async_retrieve_chunks(chunks).await?; + Ok(transmute_from_bytes_vec::(bytes)) } /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`]. @@ -242,12 +283,10 @@ impl Array { &self, chunks: &ArraySubset, ) -> Result, ArrayError> { + validate_element_size::(self.data_type())?; let array_subset = self.chunks_subset(chunks)?; - array_async_retrieve_ndarray!( - self, - array_subset.shape(), - async_retrieve_chunks_elements(chunks) - ) + let elements = self.async_retrieve_chunks_elements(chunks).await?; + elements_to_ndarray(array_subset.shape(), elements) } async fn _async_decode_chunk_into_array_subset( @@ -475,7 +514,9 @@ impl Array { &self, array_subset: &ArraySubset, ) -> Result, ArrayError> { - array_async_retrieve_elements!(self, async_retrieve_array_subset(array_subset)) + validate_element_size::(self.data_type())?; + let bytes = self.async_retrieve_array_subset(array_subset).await?; + Ok(transmute_from_bytes_vec::(bytes)) } #[cfg(feature = "ndarray")] @@ -493,11 +534,11 @@ impl Array { &self, array_subset: &ArraySubset, ) -> Result, ArrayError> { - array_async_retrieve_ndarray!( - self, - array_subset.shape(), - async_retrieve_array_subset_elements(array_subset) - ) + // validate_element_size::(self.data_type())?; // in async_retrieve_array_subset_elements + let elements = self + .async_retrieve_array_subset_elements(array_subset) + .await?; + elements_to_ndarray(array_subset.shape(), elements) } /// Read and decode the `chunk_subset` of the chunk at `chunk_indices` into its bytes. @@ -565,10 +606,11 @@ impl Array { chunk_indices: &[u64], chunk_subset: &ArraySubset, ) -> Result, ArrayError> { - array_async_retrieve_elements!( - self, - async_retrieve_chunk_subset(chunk_indices, chunk_subset) - ) + validate_element_size::(self.data_type())?; + let bytes = self + .async_retrieve_chunk_subset(chunk_indices, chunk_subset) + .await?; + Ok(transmute_from_bytes_vec::(bytes)) } #[cfg(feature = "ndarray")] @@ -588,11 +630,11 @@ impl Array { chunk_indices: &[u64], chunk_subset: &ArraySubset, ) -> Result, ArrayError> { - array_async_retrieve_ndarray!( - self, - chunk_subset.shape(), - async_retrieve_chunk_subset_elements(chunk_indices, chunk_subset) - ) + // validate_element_size::(self.data_type())?; // in async_retrieve_chunk_subset_elements + let elements = self + .async_retrieve_chunk_subset_elements(chunk_indices, chunk_subset) + .await?; + elements_to_ndarray(chunk_subset.shape(), elements) } /// Initialises a partial decoder for the chunk at `chunk_indices` with optional parallelism. diff --git a/src/array/array_sync_readable.rs b/src/array/array_sync_readable.rs index 18d6b77a..d9cc1ff7 100644 --- a/src/array/array_sync_readable.rs +++ b/src/array/array_sync_readable.rs @@ -12,50 +12,13 @@ use super::{ codec::{ ArrayCodecTraits, ArrayPartialDecoderTraits, ArrayToBytesCodecTraits, StoragePartialDecoder, }, - unravel_index, + transmute_from_bytes_vec, unravel_index, unsafe_cell_slice::UnsafeCellSlice, - Array, ArrayCreateError, ArrayError, ArrayMetadata, + validate_element_size, Array, ArrayCreateError, ArrayError, ArrayMetadata, }; -macro_rules! array_retrieve_elements { - ( $self:expr, $func:ident($($arg:tt)*) ) => { - if $self.data_type.size() != std::mem::size_of::() { - Err(ArrayError::IncompatibleElementSize( - $self.data_type.size(), - std::mem::size_of::(), - )) - } else { - let bytes = $self.$func($($arg)*)?; - let elements = crate::array::transmute_from_bytes_vec::(bytes); - Ok(elements) - } - }; -} - #[cfg(feature = "ndarray")] -macro_rules! array_retrieve_ndarray { - ( $self:expr, $shape:expr, $func:ident($($arg:tt)*) ) => { - if $self.data_type.size() != std::mem::size_of::() { - Err(ArrayError::IncompatibleElementSize( - $self.data_type.size(), - std::mem::size_of::(), - )) - } else { - let elements = $self.$func($($arg)*)?; - let length = elements.len(); - ndarray::ArrayD::::from_shape_vec( - super::iter_u64_to_usize($shape.iter()), - elements, - ) - .map_err(|_| { - ArrayError::CodecError(crate::array::codec::CodecError::UnexpectedChunkDecodedSize( - length * std::mem::size_of::(), - $shape.iter().product::() * std::mem::size_of::() as u64, - )) - }) - } - }; -} +use super::elements_to_ndarray; impl Array { /// Create an array in `storage` at `path`. The metadata is read from the store. @@ -74,7 +37,7 @@ impl Array { Self::new_with_metadata(storage, path, metadata) } - /// Read and decode the chunk at `chunk_indices` into its bytes. + /// Read and decode the chunk at `chunk_indices` into its bytes if it exists. /// /// # Errors /// Returns an [`ArrayError`] if @@ -84,7 +47,10 @@ impl Array { /// /// # Panics /// Panics if the number of elements in the chunk exceeds `usize::MAX`. - pub fn retrieve_chunk(&self, chunk_indices: &[u64]) -> Result, ArrayError> { + pub fn retrieve_chunk_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { let storage_handle = Arc::new(StorageHandle::new(&*self.storage)); let storage_transformer = self .storage_transformers() @@ -96,8 +62,8 @@ impl Array { self.chunk_key_encoding(), ) .map_err(ArrayError::StorageError)?; - let chunk_representation = self.chunk_array_representation(chunk_indices)?; if let Some(chunk_encoded) = chunk_encoded { + let chunk_representation = self.chunk_array_representation(chunk_indices)?; let chunk_decoded = self .codecs() .decode_opt(chunk_encoded, &chunk_representation, self.parallel_codecs()) @@ -105,7 +71,7 @@ impl Array { let chunk_decoded_size = chunk_representation.num_elements_usize() * chunk_representation.data_type().size(); if chunk_decoded.len() == chunk_decoded_size { - Ok(chunk_decoded) + Ok(Some(chunk_decoded)) } else { Err(ArrayError::UnexpectedChunkDecodedSize( chunk_decoded.len(), @@ -113,12 +79,50 @@ impl Array { )) } } else { + Ok(None) + } + } + + /// Read and decode the chunk at `chunk_indices` into its bytes or the fill value if it does not exist. + /// + /// # Errors + /// Returns an [`ArrayError`] if + /// - `chunk_indices` are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + /// + /// # Panics + /// Panics if the number of elements in the chunk exceeds `usize::MAX`. + pub fn retrieve_chunk(&self, chunk_indices: &[u64]) -> Result, ArrayError> { + let chunk = self.retrieve_chunk_if_exists(chunk_indices)?; + if let Some(chunk) = chunk { + Ok(chunk) + } else { + let chunk_representation = self.chunk_array_representation(chunk_indices)?; let fill_value = chunk_representation.fill_value().as_ne_bytes(); Ok(fill_value.repeat(chunk_representation.num_elements_usize())) } } - /// Read and decode the chunk at `chunk_indices` into a vector of its elements. + /// Read and decode the chunk at `chunk_indices` into a vector of its elements if it exists. + /// + /// # Errors + /// Returns an [`ArrayError`] if + /// - the size of `T` does not match the data type size, + /// - the decoded bytes cannot be transmuted, + /// - `chunk_indices` are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + pub fn retrieve_chunk_elements_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { + validate_element_size::(self.data_type())?; + let bytes = self.retrieve_chunk_if_exists(chunk_indices)?; + Ok(bytes.map(|bytes| transmute_from_bytes_vec::(bytes))) + } + + /// Read and decode the chunk at `chunk_indices` into a vector of its elements or the fill value if it does not exist. /// /// # Errors /// Returns an [`ArrayError`] if @@ -131,11 +135,43 @@ impl Array { &self, chunk_indices: &[u64], ) -> Result, ArrayError> { - array_retrieve_elements!(self, retrieve_chunk(chunk_indices)) + validate_element_size::(self.data_type())?; + let bytes = self.retrieve_chunk(chunk_indices)?; + Ok(transmute_from_bytes_vec::(bytes)) + } + + #[cfg(feature = "ndarray")] + /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`] if it exists. + /// + /// # Errors + /// Returns an [`ArrayError`] if: + /// - the size of `T` does not match the data type size, + /// - the decoded bytes cannot be transmuted, + /// - the chunk indices are invalid, + /// - there is a codec decoding error, or + /// - an underlying store error. + /// + /// # Panics + /// Will panic if a chunk dimension is larger than `usize::MAX`. + pub fn retrieve_chunk_ndarray_if_exists( + &self, + chunk_indices: &[u64], + ) -> Result>, ArrayError> { + // validate_element_size::(self.data_type())?; // in retrieve_chunk_elements_if_exists + let shape = self + .chunk_grid() + .chunk_shape_u64(chunk_indices, self.shape())? + .ok_or_else(|| ArrayError::InvalidChunkGridIndicesError(chunk_indices.to_vec()))?; + let elements = self.retrieve_chunk_elements_if_exists::(chunk_indices)?; + if let Some(elements) = elements { + Ok(Some(elements_to_ndarray(&shape, elements)?)) + } else { + Ok(None) + } } #[cfg(feature = "ndarray")] - /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`]. + /// Read and decode the chunk at `chunk_indices` into an [`ndarray::ArrayD`]. It is filled with the fill value if it does not exist. /// /// # Errors /// Returns an [`ArrayError`] if: @@ -151,11 +187,12 @@ impl Array { &self, chunk_indices: &[u64], ) -> Result, ArrayError> { + // validate_element_size::(self.data_type())?; // in retrieve_chunk_elements let shape = self .chunk_grid() .chunk_shape_u64(chunk_indices, self.shape())? .ok_or_else(|| ArrayError::InvalidChunkGridIndicesError(chunk_indices.to_vec()))?; - array_retrieve_ndarray!(self, shape, retrieve_chunk_elements(chunk_indices)) + elements_to_ndarray(&shape, self.retrieve_chunk_elements::(chunk_indices)?) } /// Read and decode the chunks at `chunks` into their bytes. @@ -264,7 +301,9 @@ impl Array { chunks: &ArraySubset, parallel: bool, ) -> Result, ArrayError> { - array_retrieve_elements!(self, retrieve_chunks_opt(chunks, parallel)) + validate_element_size::(self.data_type())?; + let bytes = self.retrieve_chunks_opt(chunks, parallel)?; + Ok(transmute_from_bytes_vec::(bytes)) } /// Serial version of [`Array::retrieve_chunks_elements_opt`]. @@ -298,12 +337,10 @@ impl Array { chunks: &ArraySubset, parallel: bool, ) -> Result, ArrayError> { + // validate_element_size::(self.data_type())?; // in retrieve_chunks_elements_opt let array_subset = self.chunks_subset(chunks)?; - array_retrieve_ndarray!( - self, - array_subset.shape(), - retrieve_chunks_elements_opt(chunks, parallel) - ) + let elements = self.retrieve_chunks_elements_opt::(chunks, parallel)?; + elements_to_ndarray(array_subset.shape(), elements) } #[cfg(feature = "ndarray")] @@ -516,7 +553,9 @@ impl Array { array_subset: &ArraySubset, parallel: bool, ) -> Result, ArrayError> { - array_retrieve_elements!(self, retrieve_array_subset_opt(array_subset, parallel)) + validate_element_size::(self.data_type())?; + let bytes = self.retrieve_array_subset_opt(array_subset, parallel)?; + Ok(transmute_from_bytes_vec::(bytes)) } /// Serial version of [`Array::retrieve_array_subset_elements_opt`]. @@ -553,11 +592,9 @@ impl Array { array_subset: &ArraySubset, parallel: bool, ) -> Result, ArrayError> { - array_retrieve_ndarray!( - self, - array_subset.shape(), - retrieve_array_subset_elements_opt(array_subset, parallel) - ) + // validate_element_size::(self.data_type())?; // in retrieve_array_subset_elements_opt + let elements = self.retrieve_array_subset_elements_opt::(array_subset, parallel)?; + elements_to_ndarray(array_subset.shape(), elements) } #[cfg(feature = "ndarray")] @@ -643,7 +680,9 @@ impl Array { chunk_indices: &[u64], chunk_subset: &ArraySubset, ) -> Result, ArrayError> { - array_retrieve_elements!(self, retrieve_chunk_subset(chunk_indices, chunk_subset)) + validate_element_size::(self.data_type())?; + let bytes = self.retrieve_chunk_subset(chunk_indices, chunk_subset)?; + Ok(transmute_from_bytes_vec::(bytes)) } #[cfg(feature = "ndarray")] @@ -663,11 +702,9 @@ impl Array { chunk_indices: &[u64], chunk_subset: &ArraySubset, ) -> Result, ArrayError> { - array_retrieve_ndarray!( - self, - chunk_subset.shape(), - retrieve_chunk_subset_elements(chunk_indices, chunk_subset) - ) + // validate_element_size::(self.data_type())?; // in retrieve_chunk_subset_elements + let elements = self.retrieve_chunk_subset_elements::(chunk_indices, chunk_subset)?; + elements_to_ndarray(chunk_subset.shape(), elements) } /// Initialises a partial decoder for the chunk at `chunk_indices` with optional parallelism.