use crate::{ArrayBytes, ArrayBytesRaw};
#[derive(Clone, Debug)]
pub struct ArrayBytesOptional<'a> {
data: Box<ArrayBytes<'a>>,
mask: ArrayBytesRaw<'a>,
}
impl<'a> ArrayBytesOptional<'a> {
pub fn new(data: impl Into<Box<ArrayBytes<'a>>>, mask: impl Into<ArrayBytesRaw<'a>>) -> Self {
let data = data.into();
let mask = mask.into();
Self { data, mask }
}
#[must_use]
pub fn data(&self) -> &ArrayBytes<'a> {
&self.data
}
#[must_use]
pub fn mask(&self) -> &ArrayBytesRaw<'a> {
&self.mask
}
#[must_use]
pub fn num_elements(&self) -> usize {
self.mask.len()
}
#[must_use]
pub fn into_parts(self) -> (Box<ArrayBytes<'a>>, ArrayBytesRaw<'a>) {
(self.data, self.mask)
}
#[must_use]
pub fn into_owned(self) -> ArrayBytesOptional<'static> {
ArrayBytesOptional {
data: Box::new((*self.data).into_owned()),
mask: self.mask.into_owned().into(),
}
}
}
impl PartialEq for ArrayBytesOptional<'_> {
fn eq(&self, other: &Self) -> bool {
if self.mask != other.mask {
return false;
}
match (self.data.as_ref(), other.data.as_ref()) {
(ArrayBytes::Fixed(a_data), ArrayBytes::Fixed(b_data)) => {
let num_elements = self.mask.len();
if num_elements == 0 {
return a_data == b_data;
}
let elem_size = a_data.len() / num_elements;
if elem_size == 0 {
return a_data == b_data;
}
for (i, &mask_val) in self.mask.iter().enumerate() {
if mask_val != 0 {
let start = i * elem_size;
let end = start + elem_size;
if a_data.get(start..end) != b_data.get(start..end) {
return false;
}
}
}
true
}
(ArrayBytes::Variable(a_var), ArrayBytes::Variable(b_var)) => {
let a_offsets = a_var.offsets();
let b_offsets = b_var.offsets();
for (i, &mask_val) in self.mask.iter().enumerate() {
if mask_val != 0 {
let a_start = a_offsets[i];
let a_end = a_offsets[i + 1];
let b_start = b_offsets[i];
let b_end = b_offsets[i + 1];
if a_var.bytes().get(a_start..a_end) != b_var.bytes().get(b_start..b_end) {
return false;
}
}
}
true
}
(ArrayBytes::Optional(a_inner), ArrayBytes::Optional(b_inner)) => {
a_inner == b_inner
}
(ArrayBytes::Fixed(_) | ArrayBytes::Optional(_), ArrayBytes::Variable(_))
| (ArrayBytes::Fixed(_) | ArrayBytes::Variable(_), ArrayBytes::Optional(_))
| (ArrayBytes::Variable(_) | ArrayBytes::Optional(_), ArrayBytes::Fixed(_)) => false,
}
}
}
impl Eq for ArrayBytesOptional<'_> {}