pub enum ArrayBytes<'a> {
Fixed(Cow<'a, [u8]>),
Variable(ArrayBytesVariableLength<'a>),
Optional(ArrayBytesOptional<'a>),
}Expand description
Fixed or variable length array bytes.
Variants§
Fixed(Cow<'a, [u8]>)
Bytes for a fixed length array.
These represent elements in C-contiguous order (i.e. row-major order) where the last dimension varies the fastest.
Variable(ArrayBytesVariableLength<'a>)
Bytes and element byte offsets for a variable length array.
Optional(ArrayBytesOptional<'a>)
Bytes for an optional array (data with a validity mask).
The data can be either Fixed or Variable length. The mask is validated at construction to have 1 byte per element.
Implementations§
Source§impl<'a> ArrayBytes<'a>
impl<'a> ArrayBytes<'a>
Sourcepub fn new_flen(bytes: impl Into<Cow<'a, [u8]>>) -> ArrayBytes<'a>
pub fn new_flen(bytes: impl Into<Cow<'a, [u8]>>) -> ArrayBytes<'a>
Create a new fixed length array bytes from bytes.
bytes must be C-contiguous.
Sourcepub fn new_vlen(
bytes: impl Into<Cow<'a, [u8]>>,
offsets: ArrayBytesOffsets<'a>,
) -> Result<ArrayBytes<'a>, ArrayBytesRawOffsetsOutOfBoundsError>
pub fn new_vlen( bytes: impl Into<Cow<'a, [u8]>>, offsets: ArrayBytesOffsets<'a>, ) -> Result<ArrayBytes<'a>, ArrayBytesRawOffsetsOutOfBoundsError>
Create a new variable length array bytes from bytes and offsets.
§Errors
Returns a ArrayBytesRawOffsetsOutOfBoundsError if the last offset is out of bounds of the bytes.
Sourcepub unsafe fn new_vlen_unchecked(
bytes: impl Into<Cow<'a, [u8]>>,
offsets: ArrayBytesOffsets<'a>,
) -> ArrayBytes<'a>
pub unsafe fn new_vlen_unchecked( bytes: impl Into<Cow<'a, [u8]>>, offsets: ArrayBytesOffsets<'a>, ) -> ArrayBytes<'a>
Create a new variable length array bytes from bytes and offsets without checking the offsets.
§Safety
The last offset must be less than or equal to the length of the bytes.
Examples found in repository?
38 fn to_array_bytes<'a>(
39 data_type: &DataType,
40 elements: &'a [Self],
41 ) -> Result<zarrs::array::ArrayBytes<'a>, ElementError> {
42 Self::validate_data_type(data_type)?;
43 let mut bytes = Vec::new();
44 let mut offsets = Vec::with_capacity(elements.len() + 1);
45
46 for element in elements {
47 offsets.push(bytes.len());
48 if let Some(value) = element.0 {
49 bytes.extend_from_slice(&value.to_le_bytes());
50 }
51 }
52 offsets.push(bytes.len());
53 let offsets = unsafe {
54 // SAFETY: Constructed correctly above
55 ArrayBytesOffsets::new_unchecked(offsets)
56 };
57 unsafe { Ok(ArrayBytes::new_vlen_unchecked(bytes, offsets)) }
58 }Sourcepub fn with_optional_mask(
self,
mask: impl Into<Cow<'a, [u8]>>,
) -> ArrayBytes<'a>
pub fn with_optional_mask( self, mask: impl Into<Cow<'a, [u8]>>, ) -> ArrayBytes<'a>
Wrap the array bytes with an optional validity mask.
This creates an Optional variant that contains the current array bytes and the provided mask.
Sourcepub fn new_fill_value(
data_type: &DataType,
num_elements: u64,
fill_value: &FillValue,
) -> Result<ArrayBytes<'a>, DataTypeFillValueError>
pub fn new_fill_value( data_type: &DataType, num_elements: u64, fill_value: &FillValue, ) -> Result<ArrayBytes<'a>, DataTypeFillValueError>
Create a new ArrayBytes with num_elements composed entirely of the fill_value.
§Errors
Returns DataTypeFillValueError if the fill value is incompatible with the data type.
§Panics
Panics if num_elements exceeds usize::MAX.
Sourcepub fn into_fixed(self) -> Result<Cow<'a, [u8]>, ExpectedFixedLengthBytesError>
pub fn into_fixed(self) -> Result<Cow<'a, [u8]>, ExpectedFixedLengthBytesError>
Convert the array bytes into fixed length bytes.
§Errors
Returns an ExpectedFixedLengthBytesError if the bytes are not fixed.
Examples found in repository?
187 fn from_array_bytes(
188 data_type: &DataType,
189 bytes: ArrayBytes<'_>,
190 ) -> Result<Vec<Self>, ElementError> {
191 Self::validate_data_type(data_type)?;
192 let bytes = bytes.into_fixed()?;
193 let bytes_len = bytes.len();
194 let mut elements = Vec::with_capacity(bytes_len);
195 // NOTE: Could memcpy here
196 for byte in bytes.iter() {
197 elements.push(CustomDataTypeFloat8e3m4Element(*byte))
198 }
199 Ok(elements)
200 }More examples
179 fn from_array_bytes(
180 data_type: &DataType,
181 bytes: ArrayBytes<'_>,
182 ) -> Result<Vec<Self>, ElementError> {
183 Self::validate_data_type(data_type)?;
184 let bytes = bytes.into_fixed()?;
185 let bytes_len = bytes.len();
186 let mut elements = Vec::with_capacity(bytes_len / size_of::<CustomDataTypeUInt4Element>());
187 for byte in bytes.iter() {
188 elements.push(CustomDataTypeUInt4Element(*byte))
189 }
190 Ok(elements)
191 }177 fn from_array_bytes(
178 data_type: &DataType,
179 bytes: ArrayBytes<'_>,
180 ) -> Result<Vec<Self>, ElementError> {
181 Self::validate_data_type(data_type)?;
182 let bytes = bytes.into_fixed()?;
183 let bytes_len = bytes.len();
184 let mut elements = Vec::with_capacity(bytes_len / size_of::<CustomDataTypeUInt12Element>());
185 for chunk in bytes.as_chunks::<2>().0 {
186 elements.push(CustomDataTypeUInt12Element::from_le_bytes(*chunk))
187 }
188 Ok(elements)
189 }135 fn from_array_bytes(
136 data_type: &DataType,
137 bytes: ArrayBytes<'_>,
138 ) -> Result<Vec<Self>, ElementError> {
139 Self::validate_data_type(data_type)?;
140 let bytes = bytes.into_fixed()?;
141 let bytes_len = bytes.len();
142 let mut elements =
143 Vec::with_capacity(bytes_len / size_of::<CustomDataTypeFixedSizeBytes>());
144 for bytes in bytes
145 .as_chunks::<{ size_of::<CustomDataTypeFixedSizeBytes>() }>()
146 .0
147 {
148 elements.push(CustomDataTypeFixedSizeElement::from_ne_bytes(bytes))
149 }
150 Ok(elements)
151 }10fn sharded_array_write_read() -> Result<(), Box<dyn std::error::Error>> {
11 use std::sync::Arc;
12
13 use rayon::prelude::{IntoParallelIterator, ParallelIterator};
14 use zarrs::array::{ArraySubset, codec, data_type};
15 use zarrs::node::Node;
16 use zarrs::storage::store;
17
18 // Create a store
19 // let path = tempfile::TempDir::new()?;
20 // let mut store: ReadableWritableListableStorage =
21 // Arc::new(zarrs::filesystem::FilesystemStore::new(path.path())?);
22 // let mut store: ReadableWritableListableStorage = Arc::new(
23 // zarrs::filesystem::FilesystemStore::new("zarrs/tests/data/sharded_array_write_read.zarr")?,
24 // );
25 let mut store: ReadableWritableListableStorage = Arc::new(store::MemoryStore::new());
26 if let Some(arg1) = std::env::args().collect::<Vec<_>>().get(1)
27 && arg1 == "--usage-log"
28 {
29 let log_writer = Arc::new(std::sync::Mutex::new(
30 // std::io::BufWriter::new(
31 std::io::stdout(),
32 // )
33 ));
34 store = Arc::new(UsageLogStorageAdapter::new(store, log_writer, || {
35 chrono::Utc::now().format("[%T%.3f] ").to_string()
36 }));
37 }
38
39 // Create the root group
40 zarrs::group::GroupBuilder::new()
41 .build(store.clone(), "/")?
42 .store_metadata()?;
43
44 // Create a group with attributes
45 let group_path = "/group";
46 let mut group = zarrs::group::GroupBuilder::new().build(store.clone(), group_path)?;
47 group
48 .attributes_mut()
49 .insert("foo".into(), serde_json::Value::String("bar".into()));
50 group.store_metadata()?;
51
52 // Create an array
53 let array_path = "/group/array";
54 let subchunk_shape = vec![4, 4];
55 let array = zarrs::array::ArrayBuilder::new(
56 vec![8, 8], // array shape
57 vec![4, 8], // chunk (shard) shape
58 data_type::uint16(),
59 0u16,
60 )
61 .subchunk_shape(subchunk_shape.clone())
62 .bytes_to_bytes_codecs(vec![
63 #[cfg(feature = "gzip")]
64 Arc::new(codec::GzipCodec::new(5)?),
65 ])
66 .dimension_names(["y", "x"].into())
67 // .storage_transformers(vec![].into())
68 .build(store.clone(), array_path)?;
69
70 // Write array metadata to store
71 array.store_metadata()?;
72
73 // The array metadata is
74 println!(
75 "The array metadata is:\n{}\n",
76 array.metadata().to_string_pretty()
77 );
78
79 // Use default codec options (concurrency etc)
80 let options = CodecOptions::default();
81
82 // Write some shards (in parallel)
83 (0..2).into_par_iter().try_for_each(|s| {
84 let chunk_grid = array.chunk_grid();
85 let chunk_indices = vec![s, 0];
86 if let Some(chunk_shape) = chunk_grid.chunk_shape(&chunk_indices)? {
87 let chunk_array = ndarray::ArrayD::<u16>::from_shape_fn(
88 chunk_shape
89 .iter()
90 .map(|u| u.get() as usize)
91 .collect::<Vec<_>>(),
92 |ij| {
93 (s * chunk_shape[0].get() * chunk_shape[1].get()
94 + ij[0] as u64 * chunk_shape[1].get()
95 + ij[1] as u64) as u16
96 },
97 );
98 array.store_chunk(&chunk_indices, chunk_array)
99 } else {
100 Err(zarrs::array::ArrayError::InvalidChunkGridIndicesError(
101 chunk_indices.to_vec(),
102 ))
103 }
104 })?;
105
106 // Read the whole array
107 let data_all: ArrayD<u16> = array.retrieve_array_subset(&array.subset_all())?;
108 println!("The whole array is:\n{data_all}\n");
109
110 // Read a shard back from the store
111 let shard_indices = vec![1, 0];
112 let data_shard: ArrayD<u16> = array.retrieve_chunk(&shard_indices)?;
113 println!("Shard [1,0] is:\n{data_shard}\n");
114
115 // Read a subchunk from the store
116 let subset_chunk_1_0 = ArraySubset::new_with_ranges(&[4..8, 0..4]);
117 let data_chunk: ArrayD<u16> = array.retrieve_array_subset(&subset_chunk_1_0)?;
118 println!("Chunk [1,0] is:\n{data_chunk}\n");
119
120 // Read the central 4x2 subset of the array
121 let subset_4x2 = ArraySubset::new_with_ranges(&[2..6, 3..5]); // the center 4x2 region
122 let data_4x2: ArrayD<u16> = array.retrieve_array_subset(&subset_4x2)?;
123 println!("The middle 4x2 subset is:\n{data_4x2}\n");
124
125 // Decode subchunks
126 // In some cases, it might be preferable to decode subchunks in a shard directly.
127 // If using the partial decoder, then the shard index will only be read once from the store.
128 let partial_decoder = array.partial_decoder(&[0, 0])?;
129 println!("Decoded subchunks:");
130 for subchunk_subset in [
131 ArraySubset::new_with_start_shape(vec![0, 0], subchunk_shape.clone())?,
132 ArraySubset::new_with_start_shape(vec![0, 4], subchunk_shape.clone())?,
133 ] {
134 println!("{subchunk_subset}");
135 let decoded_subchunk_bytes = partial_decoder.partial_decode(&subchunk_subset, &options)?;
136 let ndarray = bytes_to_ndarray::<u16>(
137 &subchunk_shape,
138 decoded_subchunk_bytes.into_fixed()?.into_owned(),
139 )?;
140 println!("{ndarray}\n");
141 }
142
143 // Show the hierarchy
144 let node = Node::open(&store, "/").unwrap();
145 let tree = node.hierarchy_tree();
146 println!("The Zarr hierarchy tree is:\n{}", tree);
147
148 println!(
149 "The keys in the store are:\n[{}]",
150 store.list().unwrap_or_default().iter().format(", ")
151 );
152
153 Ok(())
154}Sourcepub fn into_variable(
self,
) -> Result<ArrayBytesVariableLength<'a>, ExpectedVariableLengthBytesError>
pub fn into_variable( self, ) -> Result<ArrayBytesVariableLength<'a>, ExpectedVariableLengthBytesError>
Convert the array bytes into variable length bytes and element byte offsets.
§Errors
Returns an ExpectedVariableLengthBytesError if the bytes are not variable.
Examples found in repository?
69 fn from_array_bytes(
70 data_type: &DataType,
71 bytes: ArrayBytes<'_>,
72 ) -> Result<Vec<Self>, ElementError> {
73 Self::validate_data_type(data_type)?;
74 let (bytes, offsets) = bytes.into_variable()?.into_parts();
75
76 let mut elements = Vec::with_capacity(offsets.len().saturating_sub(1));
77 for (curr, next) in offsets.iter().tuple_windows() {
78 let bytes = &bytes[*curr..*next];
79 if let Ok(bytes) = <[u8; 4]>::try_from(bytes) {
80 let value = f32::from_le_bytes(bytes);
81 elements.push(CustomDataTypeVariableSizeElement(Some(value)));
82 } else if bytes.is_empty() {
83 elements.push(CustomDataTypeVariableSizeElement(None));
84 } else {
85 panic!()
86 }
87 }
88
89 Ok(elements)
90 }More examples
8fn array_write_read() -> Result<(), Box<dyn std::error::Error>> {
9 use std::sync::Arc;
10
11 use zarrs::array::{ArrayBytes, data_type};
12 use zarrs::storage::store;
13
14 // Create a store
15 // let path = tempfile::TempDir::new()?;
16 // let mut store: ReadableWritableListableStorage =
17 // Arc::new(zarrs::filesystem::FilesystemStore::new(path.path())?);
18 // let mut store: ReadableWritableListableStorage = Arc::new(
19 // zarrs::filesystem::FilesystemStore::new("zarrs/tests/data/array_write_read.zarr")?,
20 // );
21 let mut store: ReadableWritableListableStorage = Arc::new(store::MemoryStore::new());
22 if let Some(arg1) = std::env::args().collect::<Vec<_>>().get(1)
23 && arg1 == "--usage-log"
24 {
25 let log_writer = Arc::new(std::sync::Mutex::new(
26 // std::io::BufWriter::new(
27 std::io::stdout(),
28 // )
29 ));
30 store = Arc::new(UsageLogStorageAdapter::new(store, log_writer, || {
31 chrono::Utc::now().format("[%T%.3f] ").to_string()
32 }));
33 }
34
35 // Create the root group
36 zarrs::group::GroupBuilder::new()
37 .build(store.clone(), "/")?
38 .store_metadata()?;
39
40 // Create a group with attributes
41 let group_path = "/group";
42 let mut group = zarrs::group::GroupBuilder::new().build(store.clone(), group_path)?;
43 group
44 .attributes_mut()
45 .insert("foo".into(), serde_json::Value::String("bar".into()));
46 group.store_metadata()?;
47
48 println!(
49 "The group metadata is:\n{}\n",
50 group.metadata().to_string_pretty()
51 );
52
53 // Create an array
54 let array_path = "/group/array";
55 let array = zarrs::array::ArrayBuilder::new(
56 vec![4, 4], // array shape
57 vec![2, 2], // regular chunk shape
58 data_type::string(),
59 "_",
60 )
61 // .bytes_to_bytes_codecs(vec![]) // uncompressed
62 .dimension_names(["y", "x"].into())
63 // .storage_transformers(vec![].into())
64 .build(store.clone(), array_path)?;
65
66 // Write array metadata to store
67 array.store_metadata()?;
68
69 println!(
70 "The array metadata is:\n{}\n",
71 array.metadata().to_string_pretty()
72 );
73
74 // Write some chunks
75 array.store_chunk(
76 &[0, 0],
77 ArrayD::<&str>::from_shape_vec(vec![2, 2], vec!["a", "bb", "ccc", "dddd"]).unwrap(),
78 )?;
79 array.store_chunk(
80 &[0, 1],
81 ArrayD::<&str>::from_shape_vec(vec![2, 2], vec!["4444", "333", "22", "1"]).unwrap(),
82 )?;
83 let subset_all = array.subset_all();
84 let data_all: ArrayD<String> = array.retrieve_array_subset(&subset_all)?;
85 println!("store_chunk [0, 0] and [0, 1]:\n{data_all}\n");
86
87 // Write a subset spanning multiple chunks, including updating chunks already written
88 let ndarray_subset: Array2<&str> = array![["!", "@@"], ["###", "$$$$"]];
89 array.store_array_subset(&[1..3, 1..3], ndarray_subset)?;
90 let data_all: ArrayD<String> = array.retrieve_array_subset(&subset_all)?;
91 println!("store_array_subset [1..3, 1..3]:\nndarray::ArrayD<String>\n{data_all}");
92
93 // Retrieve bytes directly, convert into a single string allocation, create a &str ndarray
94 // TODO: Add a convenience function for this?
95 let data_all: ArrayBytes = array.retrieve_array_subset(&subset_all)?;
96 let (bytes, offsets) = data_all.into_variable()?.into_parts();
97 let string = String::from_utf8(bytes.into_owned())?;
98 let elements = offsets
99 .iter()
100 .tuple_windows()
101 .map(|(&curr, &next)| &string[curr..next])
102 .collect::<Vec<&str>>();
103 let ndarray = ArrayD::<&str>::from_shape_vec(subset_all.shape_usize(), elements)?;
104 println!("ndarray::ArrayD<&str>:\n{ndarray}");
105
106 Ok(())
107}Sourcepub fn into_optional(
self,
) -> Result<ArrayBytesOptional<'a>, ExpectedOptionalBytesError>
pub fn into_optional( self, ) -> Result<ArrayBytesOptional<'a>, ExpectedOptionalBytesError>
Convert the array bytes into optional data and validity mask.
§Errors
Returns an ExpectedOptionalBytesError if the bytes are not optional.
Sourcepub fn size(&self) -> usize
pub fn size(&self) -> usize
Returns the size (in bytes) of the underlying element bytes.
This only considers the size of the element bytes, and does not include the element offsets for a variable sized array or the mask for optional arrays.
Sourcepub fn offsets(&self) -> Option<&ArrayBytesOffsets<'a>>
pub fn offsets(&self) -> Option<&ArrayBytesOffsets<'a>>
Return the byte offsets for variable sized bytes. Returns None for fixed size bytes.
Sourcepub fn into_owned(self) -> ArrayBytes<'static>
pub fn into_owned(self) -> ArrayBytes<'static>
Convert into owned ArrayBytes<'static>.
Examples found in repository?
More examples
Sourcepub fn validate(
&self,
num_elements: u64,
data_type: &DataType,
) -> Result<(), CodecError>
pub fn validate( &self, num_elements: u64, data_type: &DataType, ) -> Result<(), CodecError>
Validate that the array has a valid encoding.
For a fixed-length array, check it matches the expected size. For a variable-length array, check that the offsets are monotonically increasing and the largest offset is equal to the array length.
§Errors
Returns an error if the array is not valid.
Sourcepub fn is_fill_value(&self, fill_value: &FillValue) -> bool
pub fn is_fill_value(&self, fill_value: &FillValue) -> bool
Returns true if the array is empty for the given fill value.
Sourcepub fn extract_array_subset(
&self,
indexer: &dyn Indexer,
array_shape: &[u64],
data_type: &DataType,
) -> Result<ArrayBytes<'_>, CodecError>
pub fn extract_array_subset( &self, indexer: &dyn Indexer, array_shape: &[u64], data_type: &DataType, ) -> Result<ArrayBytes<'_>, CodecError>
Extract a subset of the array bytes.
§Errors
Returns a CodecError::IncompatibleIndexer if the indexer is incompatible with subset.
§Panics
Panics if indices in the subset exceed usize::MAX.
Trait Implementations§
Source§impl<'a> Clone for ArrayBytes<'a>
impl<'a> Clone for ArrayBytes<'a>
Source§fn clone(&self) -> ArrayBytes<'a>
fn clone(&self) -> ArrayBytes<'a>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<'a> Debug for ArrayBytes<'a>
impl<'a> Debug for ArrayBytes<'a>
Source§impl<'a> From<&'a [u8]> for ArrayBytes<'a>
impl<'a> From<&'a [u8]> for ArrayBytes<'a>
Source§fn from(bytes: &'a [u8]) -> ArrayBytes<'a>
fn from(bytes: &'a [u8]) -> ArrayBytes<'a>
Source§impl<'a> From<ArrayBytesOptional<'a>> for ArrayBytes<'a>
impl<'a> From<ArrayBytesOptional<'a>> for ArrayBytes<'a>
Source§fn from(value: ArrayBytesOptional<'a>) -> ArrayBytes<'a>
fn from(value: ArrayBytesOptional<'a>) -> ArrayBytes<'a>
Source§impl<'a> From<ArrayBytesVariableLength<'a>> for ArrayBytes<'a>
impl<'a> From<ArrayBytesVariableLength<'a>> for ArrayBytes<'a>
Source§fn from(value: ArrayBytesVariableLength<'a>) -> ArrayBytes<'a>
fn from(value: ArrayBytesVariableLength<'a>) -> ArrayBytes<'a>
Source§impl FromArrayBytes for ArrayBytes<'static>
impl FromArrayBytes for ArrayBytes<'static>
Source§fn from_array_bytes(
bytes: ArrayBytes<'static>,
_shape: &[u64],
_data_type: &DataType,
) -> Result<Self, ArrayError>
fn from_array_bytes( bytes: ArrayBytes<'static>, _shape: &[u64], _data_type: &DataType, ) -> Result<Self, ArrayError>
Source§fn from_array_bytes_arc(
bytes: Arc<ArrayBytes<'static>>,
shape: &[u64],
data_type: &DataType,
) -> Result<Self, ArrayError>
fn from_array_bytes_arc( bytes: Arc<ArrayBytes<'static>>, shape: &[u64], data_type: &DataType, ) -> Result<Self, ArrayError>
Source§impl<'a> IntoArrayBytes<'a> for ArrayBytes<'a>
impl<'a> IntoArrayBytes<'a> for ArrayBytes<'a>
Source§fn into_array_bytes(
self,
_data_type: &DataType,
) -> Result<ArrayBytes<'a>, ElementError>
fn into_array_bytes( self, _data_type: &DataType, ) -> Result<ArrayBytes<'a>, ElementError>
Source§impl<'a> PartialEq for ArrayBytes<'a>
impl<'a> PartialEq for ArrayBytes<'a>
impl<'a> Eq for ArrayBytes<'a>
impl<'a> StructuralPartialEq for ArrayBytes<'a>
Auto Trait Implementations§
impl<'a> Freeze for ArrayBytes<'a>
impl<'a> Send for ArrayBytes<'a>
impl<'a> Sync for ArrayBytes<'a>
impl<'a> RefUnwindSafe for ArrayBytes<'a>
impl<'a> Unpin for ArrayBytes<'a>
impl<'a> UnsafeUnpin for ArrayBytes<'a>
impl<'a> UnwindSafe for ArrayBytes<'a>
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
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
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>
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>
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