use crate::data::primitive::{Primitive, PrimitiveArrayData};
use crate::data::types::RunEndType;
use crate::data::ArrayDataLayout;
use crate::{ArrayData, ArrayDataBuilder, Buffers};
use arrow_buffer::buffer::{RunEndBuffer, ScalarBuffer};
use arrow_buffer::ArrowNativeType;
use arrow_schema::DataType;
mod private {
use super::*;
pub trait RunEndSealed {
const ENDS_TYPE: DataType;
fn downcast_ref(data: &ArrayDataRun) -> Option<&RunArrayData<Self>>
where
Self: RunEnd;
fn downcast(data: ArrayDataRun) -> Option<RunArrayData<Self>>
where
Self: RunEnd;
fn upcast(v: RunArrayData<Self>) -> ArrayDataRun
where
Self: RunEnd;
}
}
pub trait RunEnd: private::RunEndSealed + ArrowNativeType + Primitive {
const TYPE: RunEndType;
}
macro_rules! run_end {
($t:ty,$v:ident) => {
impl RunEnd for $t {
const TYPE: RunEndType = RunEndType::$v;
}
impl private::RunEndSealed for $t {
const ENDS_TYPE: DataType = DataType::$v;
fn downcast_ref(data: &ArrayDataRun) -> Option<&RunArrayData<Self>> {
match data {
ArrayDataRun::$v(v) => Some(v),
_ => None,
}
}
fn downcast(data: ArrayDataRun) -> Option<RunArrayData<Self>> {
match data {
ArrayDataRun::$v(v) => Some(v),
_ => None,
}
}
fn upcast(v: RunArrayData<Self>) -> ArrayDataRun {
ArrayDataRun::$v(v)
}
}
};
}
run_end!(i16, Int16);
run_end!(i32, Int32);
run_end!(i64, Int64);
macro_rules! run_op {
($array:ident, $op:block) => {
match $array {
ArrayDataRun::Int16($array) => $op
ArrayDataRun::Int32($array) => $op
ArrayDataRun::Int64($array) => $op
}
};
}
#[derive(Debug, Clone)]
pub enum ArrayDataRun {
Int16(RunArrayData<i16>),
Int32(RunArrayData<i32>),
Int64(RunArrayData<i64>),
}
impl ArrayDataRun {
pub fn downcast_ref<E: RunEnd>(&self) -> Option<&RunArrayData<E>> {
<E as private::RunEndSealed>::downcast_ref(self)
}
pub fn downcast<E: RunEnd>(self) -> Option<RunArrayData<E>> {
<E as private::RunEndSealed>::downcast(self)
}
#[inline]
pub fn values(&self) -> &ArrayData {
let s = self;
run_op!(s, { s.values() })
}
pub fn slice(&self, offset: usize, len: usize) -> Self {
let s = self;
run_op!(s, { s.slice(offset, len).into() })
}
pub(crate) fn layout(&self) -> ArrayDataLayout<'_> {
let s = self;
run_op!(s, { s.layout() })
}
pub(crate) unsafe fn from_raw(builder: ArrayDataBuilder, run: RunEndType) -> Self {
use RunEndType::*;
match run {
Int16 => Self::Int16(RunArrayData::from_raw(builder)),
Int32 => Self::Int32(RunArrayData::from_raw(builder)),
Int64 => Self::Int64(RunArrayData::from_raw(builder)),
}
}
}
impl<E: RunEnd> From<RunArrayData<E>> for ArrayDataRun {
fn from(value: RunArrayData<E>) -> Self {
<E as private::RunEndSealed>::upcast(value)
}
}
#[derive(Debug, Clone)]
pub struct RunArrayData<E: RunEnd> {
data_type: DataType,
run_ends: RunEndBuffer<E>,
children: Box<[ArrayData; 2]>,
}
impl<E: RunEnd> RunArrayData<E> {
pub unsafe fn new_unchecked(
data_type: DataType,
run_ends: RunEndBuffer<E>,
values: ArrayData,
) -> Self {
let inner = run_ends.inner();
let child = ArrayDataBuilder::new(E::ENDS_TYPE)
.len(inner.len())
.buffers(vec![inner.inner().clone()])
.build_unchecked();
Self {
data_type,
run_ends,
children: Box::new([child, values]),
}
}
pub(crate) unsafe fn from_raw(builder: ArrayDataBuilder) -> Self {
let mut iter = builder.child_data.into_iter();
let child1 = iter.next().unwrap();
let child2 = iter.next().unwrap();
let p = ScalarBuffer::new(child1.buffers[0].clone(), child1.offset, child1.len);
let run_ends = RunEndBuffer::new_unchecked(p, builder.offset, builder.len);
Self {
run_ends,
data_type: builder.data_type,
children: Box::new([child1, child2]),
}
}
#[inline]
pub fn len(&self) -> usize {
self.run_ends.len()
}
#[inline]
pub fn offset(&self) -> usize {
self.run_ends.offset()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.run_ends.is_empty()
}
#[inline]
pub fn run_ends(&self) -> &RunEndBuffer<E> {
&self.run_ends
}
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
#[inline]
pub fn values(&self) -> &ArrayData {
&self.children[1]
}
pub fn into_parts(self) -> (DataType, RunEndBuffer<E>, ArrayData) {
let child = self.children.into_iter().nth(1).unwrap();
(self.data_type, self.run_ends, child)
}
pub fn slice(&self, offset: usize, len: usize) -> Self {
Self {
data_type: self.data_type.clone(),
run_ends: self.run_ends.slice(offset, len),
children: self.children.clone(),
}
}
pub(crate) fn layout(&self) -> ArrayDataLayout<'_> {
ArrayDataLayout {
data_type: &self.data_type,
len: self.run_ends.len(),
offset: self.run_ends.offset(),
nulls: None,
buffers: Buffers::default(),
child_data: self.children.as_ref(),
}
}
}