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;
#[cfg(feature = "arrow")]
mod data;
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]
pub fn get(&self, i: usize) -> Option<T> {
if !self.is_null(i) {
unsafe { Some(self.value_unchecked(i)) }
} else {
None
}
}
#[inline]
pub fn slice(&mut self, offset: usize, length: usize) {
assert!(
offset + length <= self.len(),
"offset + length may not exceed length of array"
);
unsafe { self.slice_unchecked(offset, length) }
}
#[inline]
pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
self.validity.as_mut().and_then(|bitmap| {
bitmap.slice_unchecked(offset, length);
(bitmap.unset_bits() > 0).then(|| bitmap)
});
self.values.slice_unchecked(offset, length);
}
impl_sliced!();
impl_mut_validity!();
impl_into_array!();
#[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_slice()
}
#[must_use]
pub fn into_inner(self) -> (DataType, Buffer<T>, Option<Bitmap>) {
let Self {
data_type,
values,
validity,
} = self;
(data_type, values, validity)
}
pub fn from_inner(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>,
) -> Result<Self, Error> {
check(&data_type, &values, validity.as_ref().map(|v| v.len()))?;
Ok(unsafe { Self::from_inner_unchecked(data_type, values, validity) })
}
pub unsafe fn from_inner_unchecked(
data_type: DataType,
values: Buffer<T>,
validity: Option<Bitmap>,
) -> Self {
Self {
data_type,
values,
validity,
}
}
#[must_use]
pub fn into_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.into_mut() {
Right(values) => Right(
MutablePrimitiveArray::try_new(
self.data_type,
values,
Some(mutable_bitmap),
)
.unwrap(),
),
Left(values) => Left(PrimitiveArray::new(
self.data_type,
values,
Some(mutable_bitmap.into()),
)),
},
}
} else {
match self.values.into_mut() {
Right(values) => {
Right(MutablePrimitiveArray::try_new(self.data_type, values, None).unwrap())
}
Left(values) => Left(PrimitiveArray::new(self.data_type, 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 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> {
impl_common_array!();
fn validity(&self) -> Option<&Bitmap> {
self.validity.as_ref()
}
#[inline]
fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
Box::new(self.clone().with_validity(validity))
}
}
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)
}
}