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
impl FillValue
Sourcepub fn new(bytes: Vec<u8>) -> FillValue
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
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}
Sourcepub fn as_ne_bytes(&self) -> &[u8] ⓘ
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
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 }
Sourcepub fn equals_all(&self, bytes: &[u8]) -> bool
pub fn equals_all(&self, bytes: &[u8]) -> bool
Check if the bytes are equal to a sequence of the fill value.
Trait Implementations§
impl Eq for FillValue
impl StructuralPartialEq for FillValue
Auto Trait Implementations§
impl Freeze for FillValue
impl RefUnwindSafe for FillValue
impl Send for FillValue
impl Sync for FillValue
impl Unpin for FillValue
impl UnwindSafe for FillValue
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key
and return true
if they are equal.Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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