use crate::structs::bitmask::Bitmask;
pub trait Consolidate {
type Output;
fn consolidate(self) -> Self::Output;
}
pub fn extend_null_mask(
result_mask: &mut Option<Bitmask>,
result_len: usize,
source_mask: Option<&Bitmask>,
offset: usize,
len: usize,
) {
match (result_mask.as_mut(), source_mask) {
(Some(mask), Some(src)) => {
mask.extend((offset..offset + len).map(|i| src.get(i)));
}
(Some(mask), None) => {
for _ in 0..len {
mask.set(mask.len(), true);
}
}
(None, Some(src)) => {
let mut mask = Bitmask::new_set_all(result_len, true);
mask.extend((offset..offset + len).map(|i| src.get(i)));
*result_mask = Some(mask);
}
(None, None) => {}
}
}
#[macro_export]
macro_rules! consolidate_int_variant {
($slices:expr, $variant:ident, $ty:ty) => {{
use std::sync::Arc;
use $crate::enums::array::Array;
use $crate::enums::collections::numeric_array::NumericArray;
use $crate::structs::bitmask::Bitmask;
use $crate::structs::variants::integer::IntegerArray;
use $crate::traits::consolidate::extend_null_mask;
use $crate::traits::masked_array::MaskedArray;
let total_len: usize = $slices.iter().map(|s| s.len()).sum();
let has_nulls = $slices.iter().any(|s| {
if let Array::NumericArray(NumericArray::$variant(arr)) = &s.array {
arr.null_mask().is_some()
} else {
false
}
});
let mut result = IntegerArray::<$ty>::with_capacity(total_len, has_nulls);
let mut result_mask: Option<Bitmask> = if has_nulls {
Some(Bitmask::default())
} else {
None
};
let mut current_len = 0;
for slice in $slices {
if let Array::NumericArray(NumericArray::$variant(arr)) = &slice.array {
let data: &[$ty] = &arr.data[slice.offset..slice.offset + slice.len()];
result.extend_from_slice(data);
extend_null_mask(
&mut result_mask,
current_len,
arr.null_mask(),
slice.offset,
slice.len(),
);
current_len += slice.len();
}
}
if let Some(mask) = result_mask {
result.set_null_mask(Some(mask));
}
Array::NumericArray(NumericArray::$variant(Arc::new(result)))
}};
}
#[macro_export]
macro_rules! consolidate_float_variant {
($slices:expr, $variant:ident, $ty:ty) => {{
use std::sync::Arc;
use $crate::enums::array::Array;
use $crate::enums::collections::numeric_array::NumericArray;
use $crate::structs::bitmask::Bitmask;
use $crate::structs::variants::float::FloatArray;
use $crate::traits::consolidate::extend_null_mask;
use $crate::traits::masked_array::MaskedArray;
let total_len: usize = $slices.iter().map(|s| s.len()).sum();
let has_nulls = $slices.iter().any(|s| {
if let Array::NumericArray(NumericArray::$variant(arr)) = &s.array {
arr.null_mask().is_some()
} else {
false
}
});
let mut result = FloatArray::<$ty>::with_capacity(total_len, has_nulls);
let mut result_mask: Option<Bitmask> = if has_nulls {
Some(Bitmask::default())
} else {
None
};
let mut current_len = 0;
for slice in $slices {
if let Array::NumericArray(NumericArray::$variant(arr)) = &slice.array {
let data: &[$ty] = &arr.data[slice.offset..slice.offset + slice.len()];
result.extend_from_slice(data);
extend_null_mask(
&mut result_mask,
current_len,
arr.null_mask(),
slice.offset,
slice.len(),
);
current_len += slice.len();
}
}
if let Some(mask) = result_mask {
result.set_null_mask(Some(mask));
}
Array::NumericArray(NumericArray::$variant(Arc::new(result)))
}};
}
#[macro_export]
macro_rules! consolidate_string_variant {
($slices:expr, $variant:ident, $offset_ty:ty) => {{
use std::sync::Arc;
use $crate::Vec64;
use $crate::enums::array::Array;
use $crate::enums::collections::text_array::TextArray;
use $crate::structs::bitmask::Bitmask;
use $crate::structs::variants::string::StringArray;
use $crate::traits::consolidate::extend_null_mask;
use $crate::traits::masked_array::MaskedArray;
let total_len: usize = $slices.iter().map(|s| s.len()).sum();
let has_nulls = $slices.iter().any(|s| {
if let Array::TextArray(TextArray::$variant(arr)) = &s.array {
arr.null_mask().is_some()
} else {
false
}
});
let mut result_offsets: Vec64<$offset_ty> = Vec64::with_capacity(total_len + 1);
let mut result_data: Vec64<u8> = Vec64::new();
let mut result_mask: Option<Bitmask> = if has_nulls {
Some(Bitmask::default())
} else {
None
};
let mut current_len = 0;
result_offsets.push(0 as $offset_ty);
for slice in $slices {
if let Array::TextArray(TextArray::$variant(arr)) = &slice.array {
let offsets: &[$offset_ty] = arr.offsets.as_slice();
let data: &[u8] = arr.data.as_slice();
let start_idx = slice.offset;
let end_idx = slice.offset + slice.len();
let byte_start = offsets[start_idx] as usize;
let byte_end = offsets[end_idx] as usize;
let current_data_len = *result_offsets.last().unwrap();
result_data.extend_from_slice(&data[byte_start..byte_end]);
for i in (start_idx + 1)..=end_idx {
let adjusted_offset = (offsets[i] - offsets[start_idx]) + current_data_len;
result_offsets.push(adjusted_offset);
}
extend_null_mask(
&mut result_mask,
current_len,
arr.null_mask(),
slice.offset,
slice.len(),
);
current_len += slice.len();
}
}
let result =
StringArray::<$offset_ty>::from_parts(result_offsets, result_data, result_mask);
Array::TextArray(TextArray::$variant(Arc::new(result)))
}};
}
#[cfg(feature = "datetime")]
#[macro_export]
macro_rules! consolidate_temporal_variant {
($slices:expr, $variant:ident, $ty:ty) => {{
use std::sync::Arc;
use $crate::enums::array::Array;
use $crate::enums::collections::temporal_array::TemporalArray;
use $crate::structs::bitmask::Bitmask;
use $crate::structs::variants::datetime::DatetimeArray;
use $crate::traits::consolidate::extend_null_mask;
use $crate::traits::masked_array::MaskedArray;
let total_len: usize = $slices.iter().map(|s| s.len()).sum();
let time_unit =
if let Array::TemporalArray(TemporalArray::$variant(arr)) = &$slices[0].array {
arr.time_unit.clone()
} else {
panic!("Expected TemporalArray::{}", stringify!($variant))
};
let has_nulls = $slices.iter().any(|s| {
if let Array::TemporalArray(TemporalArray::$variant(arr)) = &s.array {
arr.null_mask().is_some()
} else {
false
}
});
let mut result = DatetimeArray::<$ty>::with_capacity(total_len, has_nulls, Some(time_unit));
let mut result_mask: Option<Bitmask> = if has_nulls {
Some(Bitmask::default())
} else {
None
};
let mut current_len = 0;
for slice in $slices {
if let Array::TemporalArray(TemporalArray::$variant(arr)) = &slice.array {
let data: &[$ty] = &arr.data[slice.offset..slice.offset + slice.len()];
result.extend_from_slice(data);
extend_null_mask(
&mut result_mask,
current_len,
arr.null_mask(),
slice.offset,
slice.len(),
);
current_len += slice.len();
}
}
if let Some(mask) = result_mask {
result.set_null_mask(Some(mask));
}
Array::TemporalArray(TemporalArray::$variant(Arc::new(result)))
}};
}