Struct FillValue

Source
pub struct FillValue(/* private fields */);
Expand description

A fill value.

Provides an element value to use for uninitialised portions of the Zarr array.

Implementations§

Source§

impl FillValue

Source

pub fn new(bytes: Vec<u8>) -> FillValue

Create a new fill value composed of bytes.

Examples found in repository?
examples/custom_data_type_fixed_size.rs (line 185)
178    fn fill_value(
179        &self,
180        fill_value_metadata: &FillValueMetadataV3,
181    ) -> Result<FillValue, DataTypeFillValueMetadataError> {
182        let err = || DataTypeFillValueMetadataError::new(self.name(), fill_value_metadata.clone());
183        let element_metadata: CustomDataTypeFixedSizeMetadata =
184            fill_value_metadata.as_custom().ok_or_else(err)?;
185        Ok(FillValue::new(element_metadata.to_ne_bytes().to_vec()))
186    }
187
188    fn metadata_fill_value(
189        &self,
190        fill_value: &FillValue,
191    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
192        let element = CustomDataTypeFixedSizeMetadata::from_ne_bytes(
193            fill_value
194                .as_ne_bytes()
195                .try_into()
196                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
197        );
198        Ok(FillValueMetadataV3::from(element))
199    }
200
201    fn size(&self) -> zarrs::array::DataTypeSize {
202        DataTypeSize::Fixed(size_of::<CustomDataTypeFixedSizeBytes>())
203    }
204
205    fn codec_bytes(&self) -> Result<&dyn DataTypeExtensionBytesCodec, DataTypeExtensionError> {
206        Ok(self)
207    }
208}
209
210/// Add support for the `bytes` codec. This must be implemented for fixed-size data types, even if they just pass-through the data type.
211impl DataTypeExtensionBytesCodec for CustomDataTypeFixedSize {
212    fn encode<'a>(
213        &self,
214        bytes: std::borrow::Cow<'a, [u8]>,
215        endianness: Option<zarrs_metadata::Endianness>,
216    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
217        if let Some(endianness) = endianness {
218            if endianness != Endianness::native() {
219                let mut bytes = bytes.into_owned();
220                for bytes in bytes.chunks_exact_mut(size_of::<CustomDataTypeFixedSizeBytes>()) {
221                    let value = CustomDataTypeFixedSizeElement::from_ne_bytes(&unsafe {
222                        bytes.try_into().unwrap_unchecked()
223                    });
224                    if endianness == Endianness::Little {
225                        bytes.copy_from_slice(&value.to_le_bytes());
226                    } else {
227                        bytes.copy_from_slice(&value.to_be_bytes());
228                    }
229                }
230                Ok(Cow::Owned(bytes))
231            } else {
232                Ok(bytes)
233            }
234        } else {
235            Err(DataTypeExtensionBytesCodecError::EndiannessNotSpecified)
236        }
237    }
238
239    fn decode<'a>(
240        &self,
241        bytes: std::borrow::Cow<'a, [u8]>,
242        endianness: Option<zarrs_metadata::Endianness>,
243    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
244        if let Some(endianness) = endianness {
245            if endianness != Endianness::native() {
246                let mut bytes = bytes.into_owned();
247                for bytes in bytes.chunks_exact_mut(size_of::<u64>() + size_of::<f32>()) {
248                    let value = if endianness == Endianness::Little {
249                        CustomDataTypeFixedSizeElement::from_le_bytes(&unsafe {
250                            bytes.try_into().unwrap_unchecked()
251                        })
252                    } else {
253                        CustomDataTypeFixedSizeElement::from_be_bytes(&unsafe {
254                            bytes.try_into().unwrap_unchecked()
255                        })
256                    };
257                    bytes.copy_from_slice(&value.to_ne_bytes());
258                }
259                Ok(Cow::Owned(bytes))
260            } else {
261                Ok(bytes)
262            }
263        } else {
264            Err(DataTypeExtensionBytesCodecError::EndiannessNotSpecified)
265        }
266    }
267}
268
269fn main() {
270    let store = std::sync::Arc::new(MemoryStore::default());
271    let array_path = "/array";
272    let fill_value = CustomDataTypeFixedSizeElement { x: 1, y: 2.3 };
273    let array = ArrayBuilder::new(
274        vec![4, 1], // array shape
275        DataType::Extension(Arc::new(CustomDataTypeFixedSize)),
276        vec![2, 1].try_into().unwrap(), // regular chunk shape
277        FillValue::new(fill_value.to_ne_bytes().to_vec()),
278    )
279    .array_to_array_codecs(vec![
280        #[cfg(feature = "transpose")]
281        Arc::new(zarrs::array::codec::TransposeCodec::new(
282            zarrs::array::codec::array_to_array::transpose::TransposeOrder::new(&[1, 0]).unwrap(),
283        )),
284    ])
285    .bytes_to_bytes_codecs(vec![
286        #[cfg(feature = "gzip")]
287        Arc::new(zarrs::array::codec::GzipCodec::new(5).unwrap()),
288        #[cfg(feature = "crc32c")]
289        Arc::new(zarrs::array::codec::Crc32cCodec::new()),
290    ])
291    // .storage_transformers(vec![].into())
292    .build(store, array_path)
293    .unwrap();
294    println!("{}", array.metadata().to_string_pretty());
295
296    let data = [
297        CustomDataTypeFixedSizeElement { x: 3, y: 4.5 },
298        CustomDataTypeFixedSizeElement { x: 6, y: 7.8 },
299    ];
300    array.store_chunk_elements(&[0, 0], &data).unwrap();
301
302    let data = array
303        .retrieve_array_subset_elements::<CustomDataTypeFixedSizeElement>(&array.subset_all())
304        .unwrap();
305
306    assert_eq!(data[0], CustomDataTypeFixedSizeElement { x: 3, y: 4.5 });
307    assert_eq!(data[1], CustomDataTypeFixedSizeElement { x: 6, y: 7.8 });
308    assert_eq!(data[2], CustomDataTypeFixedSizeElement { x: 1, y: 2.3 });
309    assert_eq!(data[3], CustomDataTypeFixedSizeElement { x: 1, y: 2.3 });
310
311    println!("{data:#?}");
312}
More examples
Hide additional examples
examples/custom_data_type_float8_e3m4.rs (line 69)
62    fn fill_value(
63        &self,
64        fill_value_metadata: &FillValueMetadataV3,
65    ) -> Result<FillValue, DataTypeFillValueMetadataError> {
66        let err = || DataTypeFillValueMetadataError::new(self.name(), fill_value_metadata.clone());
67        let element_metadata: f32 = fill_value_metadata.as_f32().ok_or_else(err)?;
68        let element = CustomDataTypeFloat8e3m4Element::from(element_metadata);
69        Ok(FillValue::new(element.to_ne_bytes().to_vec()))
70    }
71
72    fn metadata_fill_value(
73        &self,
74        fill_value: &FillValue,
75    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
76        let element = CustomDataTypeFloat8e3m4Element::from_ne_bytes(
77            fill_value
78                .as_ne_bytes()
79                .try_into()
80                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
81        );
82        Ok(FillValueMetadataV3::from(element.as_f32()))
83    }
84
85    fn size(&self) -> zarrs::array::DataTypeSize {
86        DataTypeSize::Fixed(1)
87    }
88
89    fn codec_bytes(&self) -> Result<&dyn DataTypeExtensionBytesCodec, DataTypeExtensionError> {
90        Ok(self)
91    }
92}
93
94/// Add support for the `bytes` codec. This must be implemented for fixed-size data types, even if they just pass-through the data type.
95impl DataTypeExtensionBytesCodec for CustomDataTypeFloat8e3m4 {
96    fn encode<'a>(
97        &self,
98        bytes: std::borrow::Cow<'a, [u8]>,
99        _endianness: Option<zarrs_metadata::Endianness>,
100    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
101        Ok(bytes)
102    }
103
104    fn decode<'a>(
105        &self,
106        bytes: std::borrow::Cow<'a, [u8]>,
107        _endianness: Option<zarrs_metadata::Endianness>,
108    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
109        Ok(bytes)
110    }
111}
112
113// FIXME: Not tested for correctness. Prefer a supporting crate.
114fn float32_to_float8_e3m4(val: f32) -> u8 {
115    let bits = val.to_bits();
116    let sign = ((bits >> 24) & 0x80) as u8;
117    let unbiased_exponent = ((bits >> 23) & 0xFF) as i16 - 127;
118    let mantissa = ((bits >> 19) & 0x0F) as u8;
119
120    let biased_to_exponent = unbiased_exponent + 3;
121
122    if biased_to_exponent < 0 {
123        // Flush denormals and underflowing values to zero
124        sign
125    } else if biased_to_exponent > 7 {
126        // Overflow: return ±Infinity
127        sign | 0b01110000
128    } else {
129        sign | ((biased_to_exponent as u8) << 4) | mantissa
130    }
131}
132
133// FIXME: Not tested for correctness. Prefer a supporting crate.
134fn float8_e3m4_to_float32(val: u8) -> f32 {
135    let sign = (val & 0b10000000) as u32;
136    let biased_exponent = ((val >> 4) & 0b111) as i16;
137    let mantissa = (val & 0b1111) as u32;
138
139    let f32_bits = if biased_exponent == 0 {
140        // Subnormal
141        return f32::from_bits(sign << 24 | mantissa << 19);
142    } else if biased_exponent == 7 {
143        // Infinity or NaN
144        if mantissa == 0 {
145            (sign << 24) | 0x7F800000 // ±Infinity
146        } else {
147            (sign << 24) | 0x7F800000 | (mantissa << 19) // NaN
148        }
149    } else {
150        let unbiased_exponent = biased_exponent - 3;
151        let biased_to_exponent = (unbiased_exponent + 127) as u32;
152        let new_mantissa = mantissa << 19;
153        (sign << 24) | (biased_to_exponent << 23) | new_mantissa
154    };
155    f32::from_bits(f32_bits)
156}
157
158impl From<f32> for CustomDataTypeFloat8e3m4Element {
159    fn from(value: f32) -> Self {
160        Self(float32_to_float8_e3m4(value))
161    }
162}
163
164impl CustomDataTypeFloat8e3m4Element {
165    fn to_ne_bytes(&self) -> [u8; 1] {
166        [self.0]
167    }
168
169    fn from_ne_bytes(bytes: &[u8; 1]) -> Self {
170        Self(bytes[0])
171    }
172
173    fn as_f32(&self) -> f32 {
174        float8_e3m4_to_float32(self.0)
175    }
176}
177
178/// This defines how an in-memory CustomDataTypeFloat8e3m4Element is converted into ArrayBytes before encoding via the codec pipeline.
179impl Element for CustomDataTypeFloat8e3m4Element {
180    fn validate_data_type(data_type: &DataType) -> Result<(), ArrayError> {
181        (data_type == &DataType::Extension(Arc::new(CustomDataTypeFloat8e3m4)))
182            .then_some(())
183            .ok_or(ArrayError::IncompatibleElementType)
184    }
185
186    fn into_array_bytes<'a>(
187        data_type: &DataType,
188        elements: &'a [Self],
189    ) -> Result<zarrs::array::ArrayBytes<'a>, ArrayError> {
190        Self::validate_data_type(data_type)?;
191        let mut bytes: Vec<u8> = Vec::with_capacity(elements.len());
192        for element in elements {
193            bytes.push(element.0);
194        }
195        Ok(ArrayBytes::Fixed(Cow::Owned(bytes)))
196    }
197}
198
199/// This defines how ArrayBytes are converted into a CustomDataTypeFloat8e3m4Element after decoding via the codec pipeline.
200impl ElementOwned for CustomDataTypeFloat8e3m4Element {
201    fn from_array_bytes(
202        data_type: &DataType,
203        bytes: ArrayBytes<'_>,
204    ) -> Result<Vec<Self>, ArrayError> {
205        Self::validate_data_type(data_type)?;
206        let bytes = bytes.into_fixed()?;
207        let bytes_len = bytes.len();
208        let mut elements = Vec::with_capacity(bytes_len);
209        // NOTE: Could memcpy here
210        for byte in bytes.iter() {
211            elements.push(CustomDataTypeFloat8e3m4Element(*byte))
212        }
213        Ok(elements)
214    }
215}
216
217fn main() {
218    let store = std::sync::Arc::new(MemoryStore::default());
219    let array_path = "/array";
220    let fill_value = CustomDataTypeFloat8e3m4Element::from(1.23);
221    let array = ArrayBuilder::new(
222        vec![6, 1], // array shape
223        DataType::Extension(Arc::new(CustomDataTypeFloat8e3m4)),
224        vec![5, 1].try_into().unwrap(), // regular chunk shape
225        FillValue::new(fill_value.to_ne_bytes().to_vec()),
226    )
227    .array_to_array_codecs(vec![
228        #[cfg(feature = "transpose")]
229        Arc::new(zarrs::array::codec::TransposeCodec::new(
230            zarrs::array::codec::array_to_array::transpose::TransposeOrder::new(&[1, 0]).unwrap(),
231        )),
232    ])
233    .bytes_to_bytes_codecs(vec![
234        #[cfg(feature = "gzip")]
235        Arc::new(zarrs::array::codec::GzipCodec::new(5).unwrap()),
236        #[cfg(feature = "crc32c")]
237        Arc::new(zarrs::array::codec::Crc32cCodec::new()),
238    ])
239    // .storage_transformers(vec![].into())
240    .build(store, array_path)
241    .unwrap();
242    println!("{}", array.metadata().to_string_pretty());
243
244    let data = [
245        CustomDataTypeFloat8e3m4Element::from(2.34),
246        CustomDataTypeFloat8e3m4Element::from(3.45),
247        CustomDataTypeFloat8e3m4Element::from(f32::INFINITY),
248        CustomDataTypeFloat8e3m4Element::from(f32::NEG_INFINITY),
249        CustomDataTypeFloat8e3m4Element::from(f32::NAN),
250    ];
251    array.store_chunk_elements(&[0, 0], &data).unwrap();
252
253    let data = array
254        .retrieve_array_subset_elements::<CustomDataTypeFloat8e3m4Element>(&array.subset_all())
255        .unwrap();
256
257    for f in &data {
258        println!(
259            "float8_e3m4: {:08b} f32: {}",
260            f.to_ne_bytes()[0],
261            f.as_f32()
262        );
263    }
264
265    assert_eq!(data[0], CustomDataTypeFloat8e3m4Element::from(2.34));
266    assert_eq!(data[1], CustomDataTypeFloat8e3m4Element::from(3.45));
267    assert_eq!(
268        data[2],
269        CustomDataTypeFloat8e3m4Element::from(f32::INFINITY)
270    );
271    assert_eq!(
272        data[3],
273        CustomDataTypeFloat8e3m4Element::from(f32::NEG_INFINITY)
274    );
275    assert_eq!(data[4], CustomDataTypeFloat8e3m4Element::from(f32::NAN));
276    assert_eq!(data[5], CustomDataTypeFloat8e3m4Element::from(1.23));
277}
examples/custom_data_type_variable_size.rs (line 122)
117    fn fill_value(
118        &self,
119        fill_value_metadata: &FillValueMetadataV3,
120    ) -> Result<FillValue, DataTypeFillValueMetadataError> {
121        if let Some(f) = fill_value_metadata.as_f32() {
122            Ok(FillValue::new(f.to_ne_bytes().to_vec()))
123        } else if fill_value_metadata.is_null() {
124            Ok(FillValue::new(vec![]))
125        } else {
126            Err(DataTypeFillValueMetadataError::new(
127                self.name(),
128                fill_value_metadata.clone(),
129            ))
130        }
131    }
examples/custom_data_type_uint4.rs (line 73)
64    fn fill_value(
65        &self,
66        fill_value_metadata: &FillValueMetadataV3,
67    ) -> Result<FillValue, DataTypeFillValueMetadataError> {
68        let err = || DataTypeFillValueMetadataError::new(self.name(), fill_value_metadata.clone());
69        let element_metadata: u64 = fill_value_metadata.as_u64().ok_or_else(err)?;
70        let element = CustomDataTypeUInt4Element::try_from(element_metadata).map_err(|_| {
71            DataTypeFillValueMetadataError::new(UINT4.to_string(), fill_value_metadata.clone())
72        })?;
73        Ok(FillValue::new(element.to_ne_bytes().to_vec()))
74    }
75
76    fn metadata_fill_value(
77        &self,
78        fill_value: &FillValue,
79    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
80        let element = CustomDataTypeUInt4Element::from_ne_bytes(
81            fill_value
82                .as_ne_bytes()
83                .try_into()
84                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
85        );
86        Ok(FillValueMetadataV3::from(element.as_u8()))
87    }
88
89    fn size(&self) -> zarrs::array::DataTypeSize {
90        DataTypeSize::Fixed(1)
91    }
92
93    fn codec_bytes(&self) -> Result<&dyn DataTypeExtensionBytesCodec, DataTypeExtensionError> {
94        Ok(self)
95    }
96
97    fn codec_packbits(
98        &self,
99    ) -> Result<&dyn DataTypeExtensionPackBitsCodec, DataTypeExtensionError> {
100        Ok(self)
101    }
102}
103
104/// Add support for the `bytes` codec. This must be implemented for fixed-size data types, even if they just pass-through the data type.
105impl DataTypeExtensionBytesCodec for CustomDataTypeUInt4 {
106    fn encode<'a>(
107        &self,
108        bytes: std::borrow::Cow<'a, [u8]>,
109        _endianness: Option<zarrs_metadata::Endianness>,
110    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
111        Ok(bytes)
112    }
113
114    fn decode<'a>(
115        &self,
116        bytes: std::borrow::Cow<'a, [u8]>,
117        _endianness: Option<zarrs_metadata::Endianness>,
118    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
119        Ok(bytes)
120    }
121}
122
123/// Add support for the `packbits` codec.
124impl DataTypeExtensionPackBitsCodec for CustomDataTypeUInt4 {
125    fn component_size_bits(&self) -> u64 {
126        4
127    }
128
129    fn num_components(&self) -> u64 {
130        1
131    }
132
133    fn sign_extension(&self) -> bool {
134        false
135    }
136}
137
138impl TryFrom<u64> for CustomDataTypeUInt4Element {
139    type Error = u64;
140
141    fn try_from(value: u64) -> Result<Self, Self::Error> {
142        if value < 16 {
143            Ok(Self(value as u8))
144        } else {
145            Err(value)
146        }
147    }
148}
149
150impl CustomDataTypeUInt4Element {
151    fn to_ne_bytes(&self) -> [u8; 1] {
152        [self.0]
153    }
154
155    fn from_ne_bytes(bytes: &[u8; 1]) -> Self {
156        Self(bytes[0])
157    }
158
159    fn as_u8(&self) -> u8 {
160        self.0
161    }
162}
163
164/// This defines how an in-memory CustomDataTypeUInt4Element is converted into ArrayBytes before encoding via the codec pipeline.
165impl Element for CustomDataTypeUInt4Element {
166    fn validate_data_type(data_type: &DataType) -> Result<(), ArrayError> {
167        (data_type == &DataType::Extension(Arc::new(CustomDataTypeUInt4)))
168            .then_some(())
169            .ok_or(ArrayError::IncompatibleElementType)
170    }
171
172    fn into_array_bytes<'a>(
173        data_type: &DataType,
174        elements: &'a [Self],
175    ) -> Result<zarrs::array::ArrayBytes<'a>, ArrayError> {
176        Self::validate_data_type(data_type)?;
177        let mut bytes: Vec<u8> =
178            Vec::with_capacity(elements.len() * size_of::<CustomDataTypeUInt4Element>());
179        for element in elements {
180            bytes.push(element.0);
181        }
182        Ok(ArrayBytes::Fixed(Cow::Owned(bytes)))
183    }
184}
185
186/// This defines how ArrayBytes are converted into a CustomDataTypeUInt4Element after decoding via the codec pipeline.
187impl ElementOwned for CustomDataTypeUInt4Element {
188    fn from_array_bytes(
189        data_type: &DataType,
190        bytes: ArrayBytes<'_>,
191    ) -> Result<Vec<Self>, ArrayError> {
192        Self::validate_data_type(data_type)?;
193        let bytes = bytes.into_fixed()?;
194        let bytes_len = bytes.len();
195        let mut elements = Vec::with_capacity(bytes_len / size_of::<CustomDataTypeUInt4Element>());
196        for byte in bytes.iter() {
197            elements.push(CustomDataTypeUInt4Element(*byte))
198        }
199        Ok(elements)
200    }
201}
202
203fn main() {
204    let store = std::sync::Arc::new(MemoryStore::default());
205    let array_path = "/array";
206    let fill_value = CustomDataTypeUInt4Element::try_from(15).unwrap();
207    let array = ArrayBuilder::new(
208        vec![6, 1], // array shape
209        DataType::Extension(Arc::new(CustomDataTypeUInt4)),
210        vec![5, 1].try_into().unwrap(), // regular chunk shape
211        FillValue::new(fill_value.to_ne_bytes().to_vec()),
212    )
213    .array_to_array_codecs(vec![
214        #[cfg(feature = "transpose")]
215        Arc::new(zarrs::array::codec::TransposeCodec::new(
216            zarrs::array::codec::array_to_array::transpose::TransposeOrder::new(&[1, 0]).unwrap(),
217        )),
218    ])
219    .array_to_bytes_codec(Arc::new(zarrs::array::codec::PackBitsCodec::default()))
220    .bytes_to_bytes_codecs(vec![
221        #[cfg(feature = "gzip")]
222        Arc::new(zarrs::array::codec::GzipCodec::new(5).unwrap()),
223        #[cfg(feature = "crc32c")]
224        Arc::new(zarrs::array::codec::Crc32cCodec::new()),
225    ])
226    // .storage_transformers(vec![].into())
227    .build(store, array_path)
228    .unwrap();
229    println!("{}", array.metadata().to_string_pretty());
230
231    let data = [
232        CustomDataTypeUInt4Element::try_from(1).unwrap(),
233        CustomDataTypeUInt4Element::try_from(2).unwrap(),
234        CustomDataTypeUInt4Element::try_from(3).unwrap(),
235        CustomDataTypeUInt4Element::try_from(4).unwrap(),
236        CustomDataTypeUInt4Element::try_from(5).unwrap(),
237    ];
238    array.store_chunk_elements(&[0, 0], &data).unwrap();
239
240    let data = array
241        .retrieve_array_subset_elements::<CustomDataTypeUInt4Element>(&array.subset_all())
242        .unwrap();
243
244    for f in &data {
245        println!("uint4: {:08b} u8: {}", f.as_u8(), f.as_u8());
246    }
247
248    assert_eq!(data[0], CustomDataTypeUInt4Element::try_from(1).unwrap());
249    assert_eq!(data[1], CustomDataTypeUInt4Element::try_from(2).unwrap());
250    assert_eq!(data[2], CustomDataTypeUInt4Element::try_from(3).unwrap());
251    assert_eq!(data[3], CustomDataTypeUInt4Element::try_from(4).unwrap());
252    assert_eq!(data[4], CustomDataTypeUInt4Element::try_from(5).unwrap());
253    assert_eq!(data[5], CustomDataTypeUInt4Element::try_from(15).unwrap());
254
255    let data = array
256        .retrieve_array_subset_elements::<CustomDataTypeUInt4Element>(
257            &ArraySubset::new_with_ranges(&[1..3, 0..1]),
258        )
259        .unwrap();
260    assert_eq!(data[0], CustomDataTypeUInt4Element::try_from(2).unwrap());
261    assert_eq!(data[1], CustomDataTypeUInt4Element::try_from(3).unwrap());
262}
examples/custom_data_type_uint12.rs (line 73)
64    fn fill_value(
65        &self,
66        fill_value_metadata: &FillValueMetadataV3,
67    ) -> Result<FillValue, DataTypeFillValueMetadataError> {
68        let err = || DataTypeFillValueMetadataError::new(self.name(), fill_value_metadata.clone());
69        let element_metadata: u64 = fill_value_metadata.as_u64().ok_or_else(err)?;
70        let element = CustomDataTypeUInt12Element::try_from(element_metadata).map_err(|_| {
71            DataTypeFillValueMetadataError::new(UINT12.to_string(), fill_value_metadata.clone())
72        })?;
73        Ok(FillValue::new(element.to_le_bytes().to_vec()))
74    }
75
76    fn metadata_fill_value(
77        &self,
78        fill_value: &FillValue,
79    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
80        let element = CustomDataTypeUInt12Element::from_le_bytes(
81            fill_value
82                .as_ne_bytes()
83                .try_into()
84                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
85        );
86        Ok(FillValueMetadataV3::from(element.as_u16()))
87    }
88
89    fn size(&self) -> zarrs::array::DataTypeSize {
90        DataTypeSize::Fixed(2)
91    }
92
93    fn codec_bytes(&self) -> Result<&dyn DataTypeExtensionBytesCodec, DataTypeExtensionError> {
94        Ok(self)
95    }
96
97    fn codec_packbits(
98        &self,
99    ) -> Result<&dyn DataTypeExtensionPackBitsCodec, DataTypeExtensionError> {
100        Ok(self)
101    }
102}
103
104/// Add support for the `bytes` codec. This must be implemented for fixed-size data types, even if they just pass-through the data type.
105impl DataTypeExtensionBytesCodec for CustomDataTypeUInt12 {
106    fn encode<'a>(
107        &self,
108        bytes: std::borrow::Cow<'a, [u8]>,
109        _endianness: Option<zarrs_metadata::Endianness>,
110    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
111        Ok(bytes)
112    }
113
114    fn decode<'a>(
115        &self,
116        bytes: std::borrow::Cow<'a, [u8]>,
117        _endianness: Option<zarrs_metadata::Endianness>,
118    ) -> Result<std::borrow::Cow<'a, [u8]>, DataTypeExtensionBytesCodecError> {
119        Ok(bytes)
120    }
121}
122
123/// Add support for the `packbits` codec.
124impl DataTypeExtensionPackBitsCodec for CustomDataTypeUInt12 {
125    fn component_size_bits(&self) -> u64 {
126        12
127    }
128
129    fn num_components(&self) -> u64 {
130        1
131    }
132
133    fn sign_extension(&self) -> bool {
134        false
135    }
136}
137
138impl TryFrom<u64> for CustomDataTypeUInt12Element {
139    type Error = u64;
140
141    fn try_from(value: u64) -> Result<Self, Self::Error> {
142        if value < 4096 {
143            Ok(Self(value as u16))
144        } else {
145            Err(value)
146        }
147    }
148}
149
150impl CustomDataTypeUInt12Element {
151    fn to_le_bytes(&self) -> [u8; 2] {
152        self.0.to_le_bytes()
153    }
154
155    fn from_le_bytes(bytes: [u8; 2]) -> Self {
156        Self(u16::from_le_bytes(bytes))
157    }
158
159    fn as_u16(&self) -> u16 {
160        self.0
161    }
162}
163
164/// This defines how an in-memory CustomDataTypeUInt12Element is converted into ArrayBytes before encoding via the codec pipeline.
165impl Element for CustomDataTypeUInt12Element {
166    fn validate_data_type(data_type: &DataType) -> Result<(), ArrayError> {
167        (data_type == &DataType::Extension(Arc::new(CustomDataTypeUInt12)))
168            .then_some(())
169            .ok_or(ArrayError::IncompatibleElementType)
170    }
171
172    fn into_array_bytes<'a>(
173        data_type: &DataType,
174        elements: &'a [Self],
175    ) -> Result<zarrs::array::ArrayBytes<'a>, ArrayError> {
176        Self::validate_data_type(data_type)?;
177        let mut bytes: Vec<u8> =
178            Vec::with_capacity(elements.len() * size_of::<CustomDataTypeUInt12Element>());
179        for element in elements {
180            bytes.extend_from_slice(&element.to_le_bytes());
181        }
182        Ok(ArrayBytes::Fixed(Cow::Owned(bytes)))
183    }
184}
185
186/// This defines how ArrayBytes are converted into a CustomDataTypeUInt12Element after decoding via the codec pipeline.
187impl ElementOwned for CustomDataTypeUInt12Element {
188    fn from_array_bytes(
189        data_type: &DataType,
190        bytes: ArrayBytes<'_>,
191    ) -> Result<Vec<Self>, ArrayError> {
192        Self::validate_data_type(data_type)?;
193        let bytes = bytes.into_fixed()?;
194        let bytes_len = bytes.len();
195        let mut elements = Vec::with_capacity(bytes_len / size_of::<CustomDataTypeUInt12Element>());
196        for chunk in bytes.chunks_exact(2) {
197            elements.push(CustomDataTypeUInt12Element::from_le_bytes(
198                chunk.try_into().unwrap(),
199            ))
200        }
201        Ok(elements)
202    }
203}
204
205fn main() {
206    let store = std::sync::Arc::new(MemoryStore::default());
207    let array_path = "/array";
208    let fill_value = CustomDataTypeUInt12Element::try_from(15).unwrap();
209    let array = ArrayBuilder::new(
210        vec![4096, 1], // array shape
211        DataType::Extension(Arc::new(CustomDataTypeUInt12)),
212        vec![5, 1].try_into().unwrap(), // regular chunk shape
213        FillValue::new(fill_value.to_le_bytes().to_vec()),
214    )
215    .array_to_array_codecs(vec![
216        #[cfg(feature = "transpose")]
217        Arc::new(zarrs::array::codec::TransposeCodec::new(
218            zarrs::array::codec::array_to_array::transpose::TransposeOrder::new(&[1, 0]).unwrap(),
219        )),
220    ])
221    .array_to_bytes_codec(Arc::new(zarrs::array::codec::PackBitsCodec::default()))
222    .bytes_to_bytes_codecs(vec![
223        #[cfg(feature = "gzip")]
224        Arc::new(zarrs::array::codec::GzipCodec::new(5).unwrap()),
225        #[cfg(feature = "crc32c")]
226        Arc::new(zarrs::array::codec::Crc32cCodec::new()),
227    ])
228    // .storage_transformers(vec![].into())
229    .build(store, array_path)
230    .unwrap();
231    println!("{}", array.metadata().to_string_pretty());
232
233    let data: Vec<CustomDataTypeUInt12Element> = (0..4096)
234        .into_iter()
235        .map(|i| CustomDataTypeUInt12Element::try_from(i).unwrap())
236        .collect();
237
238    array
239        .store_array_subset_elements(&array.subset_all(), &data)
240        .unwrap();
241
242    let data = array
243        .retrieve_array_subset_elements::<CustomDataTypeUInt12Element>(&array.subset_all())
244        .unwrap();
245
246    for i in 0usize..4096 {
247        let element = CustomDataTypeUInt12Element::try_from(i as u64).unwrap();
248        assert_eq!(data[i], element);
249        let element_pd = array
250            .retrieve_array_subset_elements::<CustomDataTypeUInt12Element>(
251                &ArraySubset::new_with_ranges(&[(i as u64)..i as u64 + 1, 0..1]),
252            )
253            .unwrap()[0];
254        assert_eq!(element_pd, element);
255    }
256}
Source

pub fn size(&self) -> usize

Returns the size in bytes of the fill value.

Source

pub fn as_ne_bytes(&self) -> &[u8]

Return the byte representation of the fill value.

Examples found in repository?
examples/custom_data_type_fixed_size.rs (line 194)
188    fn metadata_fill_value(
189        &self,
190        fill_value: &FillValue,
191    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
192        let element = CustomDataTypeFixedSizeMetadata::from_ne_bytes(
193            fill_value
194                .as_ne_bytes()
195                .try_into()
196                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
197        );
198        Ok(FillValueMetadataV3::from(element))
199    }
More examples
Hide additional examples
examples/custom_data_type_uint4.rs (line 82)
76    fn metadata_fill_value(
77        &self,
78        fill_value: &FillValue,
79    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
80        let element = CustomDataTypeUInt4Element::from_ne_bytes(
81            fill_value
82                .as_ne_bytes()
83                .try_into()
84                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
85        );
86        Ok(FillValueMetadataV3::from(element.as_u8()))
87    }
examples/custom_data_type_uint12.rs (line 82)
76    fn metadata_fill_value(
77        &self,
78        fill_value: &FillValue,
79    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
80        let element = CustomDataTypeUInt12Element::from_le_bytes(
81            fill_value
82                .as_ne_bytes()
83                .try_into()
84                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
85        );
86        Ok(FillValueMetadataV3::from(element.as_u16()))
87    }
examples/custom_data_type_float8_e3m4.rs (line 78)
72    fn metadata_fill_value(
73        &self,
74        fill_value: &FillValue,
75    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
76        let element = CustomDataTypeFloat8e3m4Element::from_ne_bytes(
77            fill_value
78                .as_ne_bytes()
79                .try_into()
80                .map_err(|_| DataTypeFillValueError::new(self.name(), fill_value.clone()))?,
81        );
82        Ok(FillValueMetadataV3::from(element.as_f32()))
83    }
examples/custom_data_type_variable_size.rs (line 137)
133    fn metadata_fill_value(
134        &self,
135        fill_value: &FillValue,
136    ) -> Result<FillValueMetadataV3, DataTypeFillValueError> {
137        let fill_value = fill_value.as_ne_bytes();
138        if fill_value.len() == 0 {
139            Ok(FillValueMetadataV3::Null)
140        } else if fill_value.len() == 4 {
141            let value = f32::from_ne_bytes(fill_value.try_into().unwrap());
142            Ok(FillValueMetadataV3::from(value))
143        } else {
144            Err(DataTypeFillValueError::new(self.name(), fill_value.into()))
145        }
146    }
Source

pub fn equals_all(&self, bytes: &[u8]) -> bool

Check if the bytes are equal to a sequence of the fill value.

Trait Implementations§

Source§

impl Clone for FillValue

Source§

fn clone(&self) -> FillValue

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FillValue

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for FillValue

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl From<&[u8]> for FillValue

Source§

fn from(value: &[u8]) -> FillValue

Converts to this type from the input type.
Source§

impl<const N: usize> From<&[u8; N]> for FillValue

Source§

fn from(value: &[u8; N]) -> FillValue

Converts to this type from the input type.
Source§

impl From<&str> for FillValue

Source§

fn from(value: &str) -> FillValue

Converts to this type from the input type.
Source§

impl<const N: usize> From<[u8; N]> for FillValue

Source§

fn from(value: [u8; N]) -> FillValue

Converts to this type from the input type.
Source§

impl<T> From<Complex<T>> for FillValue
where FillValue: From<T>,

Source§

fn from(value: Complex<T>) -> FillValue

Converts to this type from the input type.
Source§

impl From<String> for FillValue

Source§

fn from(value: String) -> FillValue

Converts to this type from the input type.
Source§

impl From<Vec<u8>> for FillValue

Source§

fn from(value: Vec<u8>) -> FillValue

Converts to this type from the input type.
Source§

impl From<bf16> for FillValue

Source§

fn from(value: bf16) -> FillValue

Converts to this type from the input type.
Source§

impl From<bool> for FillValue

Source§

fn from(value: bool) -> FillValue

Converts to this type from the input type.
Source§

impl From<f16> for FillValue

Source§

fn from(value: f16) -> FillValue

Converts to this type from the input type.
Source§

impl From<f32> for FillValue

Source§

fn from(value: f32) -> FillValue

Converts to this type from the input type.
Source§

impl From<f64> for FillValue

Source§

fn from(value: f64) -> FillValue

Converts to this type from the input type.
Source§

impl From<i16> for FillValue

Source§

fn from(value: i16) -> FillValue

Converts to this type from the input type.
Source§

impl From<i32> for FillValue

Source§

fn from(value: i32) -> FillValue

Converts to this type from the input type.
Source§

impl From<i64> for FillValue

Source§

fn from(value: i64) -> FillValue

Converts to this type from the input type.
Source§

impl From<i8> for FillValue

Source§

fn from(value: i8) -> FillValue

Converts to this type from the input type.
Source§

impl From<u16> for FillValue

Source§

fn from(value: u16) -> FillValue

Converts to this type from the input type.
Source§

impl From<u32> for FillValue

Source§

fn from(value: u32) -> FillValue

Converts to this type from the input type.
Source§

impl From<u64> for FillValue

Source§

fn from(value: u64) -> FillValue

Converts to this type from the input type.
Source§

impl From<u8> for FillValue

Source§

fn from(value: u8) -> FillValue

Converts to this type from the input type.
Source§

impl PartialEq for FillValue

Source§

fn eq(&self, other: &FillValue) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for FillValue

Source§

impl StructuralPartialEq for FillValue

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.