use crate::{
bitmap::{
utils::{BitmapIter, ZipValidity},
Bitmap,
},
buffer::Buffer,
datatypes::*,
error::Error,
trusted_len::TrustedLen,
types::{days_ms, f16, i256, months_days_ns, NativeType},
};
use super::Array;
use either::Either;
mod ffi;
pub(super) mod fmt;
mod from_natural;
mod iterator;
pub use iterator::*;
mod mutable;
pub use mutable::*;
#[derive(Clone)]
pub struct PrimitiveArray<T: NativeType> {
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>,
}
pub(super) fn check<T: NativeType>(
data_type: &DataType,
values: &[T],
validity_len: Option<usize>,
) -> Result<(), Error> {
if validity_len.map_or(false, |len| len != values.len()) {
return Err(Error::oos(
"validity mask length must match the number of values",
));
}
if data_type.to_physical_type() != PhysicalType::Primitive(T::PRIMITIVE) {
return Err(Error::oos(
"PrimitiveArray can only be initialized with a DataType whose physical type is Primitive",
));
}
Ok(())
}
impl<T: NativeType> PrimitiveArray<T> {
pub fn try_new(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>,
) -> Result<Self, Error> {
check(&data_type, &values, validity.as_ref().map(|v| v.len()))?;
Ok(Self {
data_type,
values,
validity,
})
}
#[inline]
#[must_use]
pub fn to(self, data_type: DataType) -> Self {
check(
&data_type,
&self.values,
self.validity.as_ref().map(|v| v.len()),
)
.unwrap();
Self {
data_type,
values: self.values,
validity: self.validity,
}
}
pub fn from_vec(values: Vec<T>) -> Self {
Self::new(T::PRIMITIVE.into(), values.into(), None)
}
#[inline]
pub fn iter(&self) -> ZipValidity<&T, std::slice::Iter<T>, BitmapIter> {
ZipValidity::new_with_validity(self.values().iter(), self.validity())
}
#[inline]
pub fn values_iter(&self) -> std::slice::Iter<T> {
self.values().iter()
}
#[inline]
pub fn len(&self) -> usize {
self.values.len()
}
#[inline]
pub fn values(&self) -> &Buffer<T> {
&self.values
}
#[inline]
pub fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
#[inline]
pub fn value(&self, i: usize) -> T {
self.values()[i]
}
#[inline]
pub unsafe fn value_unchecked(&self, i: usize) -> T {
*self.values.get_unchecked(i)
}
#[inline]
#[must_use]
pub fn slice(&self, offset: usize, length: usize) -> Self {
assert!(
offset + length <= self.len(),
"offset + length may not exceed length of array"
);
unsafe { self.slice_unchecked(offset, length) }
}
#[inline]
#[must_use]
pub unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Self {
let validity = self
.validity
.clone()
.map(|bitmap| bitmap.slice_unchecked(offset, length))
.and_then(|bitmap| (bitmap.unset_bits() > 0).then(|| bitmap));
Self {
data_type: self.data_type.clone(),
values: self.values.clone().slice_unchecked(offset, length),
validity,
}
}
#[must_use]
pub fn with_validity(mut self, validity: Option<Bitmap>) -> Self {
self.set_validity(validity);
self
}
pub fn set_validity(&mut self, validity: Option<Bitmap>) {
if matches!(&validity, Some(bitmap) if bitmap.len() != self.len()) {
panic!("validity's length must be equal to the array's length")
}
self.validity = validity;
}
#[must_use]
pub fn with_values(mut self, values: Buffer<T>) -> Self {
self.set_values(values);
self
}
pub fn set_values(&mut self, values: Buffer<T>) {
assert_eq!(
values.len(),
self.len(),
"values' length must be equal to this arrays' length"
);
self.values = values;
}
pub fn apply_validity<F: FnOnce(Bitmap) -> Bitmap>(&mut self, f: F) {
if let Some(validity) = std::mem::take(&mut self.validity) {
self.set_validity(Some(f(validity)))
}
}
pub fn get_mut_values(&mut self) -> Option<&mut [T]> {
self.values.get_mut().map(|x| x.as_mut())
}
#[must_use]
pub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>) {
let Self {
data_type,
values,
validity,
} = self;
(data_type, values, validity)
}
#[must_use]
pub fn into_mut(mut self) -> Either<Self, MutablePrimitiveArray<T>> {
use Either::*;
if let Some(bitmap) = self.validity {
match bitmap.into_mut() {
Left(bitmap) => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(bitmap),
)),
Right(mutable_bitmap) => match self.values.get_mut().map(std::mem::take) {
Some(values) => Right(
MutablePrimitiveArray::try_new(
self.data_type,
values,
Some(mutable_bitmap),
)
.unwrap(),
),
None => Left(PrimitiveArray::new(
self.data_type,
self.values,
Some(mutable_bitmap.into()),
)),
},
}
} else {
match self.values.get_mut().map(std::mem::take) {
Some(values) => {
Right(MutablePrimitiveArray::try_new(self.data_type, values, None).unwrap())
}
None => Left(PrimitiveArray::new(self.data_type, self.values, None)),
}
}
}
pub fn new_empty(data_type: DataType) -> Self {
Self::new(data_type, Buffer::new(), None)
}
#[inline]
pub fn new_null(data_type: DataType, length: usize) -> Self {
Self::new(
data_type,
vec![T::default(); length].into(),
Some(Bitmap::new_zeroed(length)),
)
}
pub fn from_values<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self::new(T::PRIMITIVE.into(), Vec::<T>::from_iter(iter).into(), None)
}
pub fn from_slice<P: AsRef<[T]>>(slice: P) -> Self {
Self::new(
T::PRIMITIVE.into(),
Vec::<T>::from(slice.as_ref()).into(),
None,
)
}
pub fn from_trusted_len_values_iter<I: TrustedLen<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter(iter).into()
}
pub unsafe fn from_trusted_len_values_iter_unchecked<I: Iterator<Item = T>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_values_iter_unchecked(iter).into()
}
pub fn from_trusted_len_iter<I: TrustedLen<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter(iter).into()
}
pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = Option<T>>>(iter: I) -> Self {
MutablePrimitiveArray::<T>::from_trusted_len_iter_unchecked(iter).into()
}
pub fn boxed(self) -> Box<dyn Array> {
Box::new(self)
}
pub fn arced(self) -> std::sync::Arc<dyn Array> {
std::sync::Arc::new(self)
}
pub fn new(data_type: DataType, values: Buffer<T>, validity: Option<Bitmap>) -> Self {
Self::try_new(data_type, values, validity).unwrap()
}
}
impl<T: NativeType> Array for PrimitiveArray<T> {
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#[inline]
fn len(&self) -> usize {
self.values.len()
}
#[inline]
fn data_type(&self) -> &DataType {
self.data_type()
}
fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
fn slice(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice(offset, length))
}
unsafe fn slice_unchecked(&self, offset: usize, length: usize) -> Box<dyn Array> {
Box::new(self.slice_unchecked(offset, length))
}
fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
Box::new(self.clone().with_validity(validity))
}
fn to_boxed(&self) -> Box<dyn Array> {
Box::new(self.clone())
}
}
pub type Int8Array = PrimitiveArray<i8>;
pub type Int16Array = PrimitiveArray<i16>;
pub type Int32Array = PrimitiveArray<i32>;
pub type Int64Array = PrimitiveArray<i64>;
pub type Int128Array = PrimitiveArray<i128>;
pub type Int256Array = PrimitiveArray<i256>;
pub type DaysMsArray = PrimitiveArray<days_ms>;
pub type MonthsDaysNsArray = PrimitiveArray<months_days_ns>;
pub type Float16Array = PrimitiveArray<f16>;
pub type Float32Array = PrimitiveArray<f32>;
pub type Float64Array = PrimitiveArray<f64>;
pub type UInt8Array = PrimitiveArray<u8>;
pub type UInt16Array = PrimitiveArray<u16>;
pub type UInt32Array = PrimitiveArray<u32>;
pub type UInt64Array = PrimitiveArray<u64>;
pub type Int8Vec = MutablePrimitiveArray<i8>;
pub type Int16Vec = MutablePrimitiveArray<i16>;
pub type Int32Vec = MutablePrimitiveArray<i32>;
pub type Int64Vec = MutablePrimitiveArray<i64>;
pub type Int128Vec = MutablePrimitiveArray<i128>;
pub type Int256Vec = MutablePrimitiveArray<i256>;
pub type DaysMsVec = MutablePrimitiveArray<days_ms>;
pub type MonthsDaysNsVec = MutablePrimitiveArray<months_days_ns>;
pub type Float16Vec = MutablePrimitiveArray<f16>;
pub type Float32Vec = MutablePrimitiveArray<f32>;
pub type Float64Vec = MutablePrimitiveArray<f64>;
pub type UInt8Vec = MutablePrimitiveArray<u8>;
pub type UInt16Vec = MutablePrimitiveArray<u16>;
pub type UInt32Vec = MutablePrimitiveArray<u32>;
pub type UInt64Vec = MutablePrimitiveArray<u64>;
impl<T: NativeType> Default for PrimitiveArray<T> {
fn default() -> Self {
PrimitiveArray::new(T::PRIMITIVE.into(), Default::default(), None)
}
}