use crate::data::ArrayDataLayout;
use crate::{ArrayData, ArrayDataBuilder, Buffers};
use arrow_buffer::buffer::ScalarBuffer;
use arrow_schema::{DataType, UnionMode};
#[derive(Debug, Clone)]
pub struct UnionArrayData {
data_type: DataType,
type_ids: ScalarBuffer<i8>,
offsets: Option<ScalarBuffer<i32>>,
children: Vec<ArrayData>,
}
impl UnionArrayData {
pub unsafe fn new_unchecked(
data_type: DataType,
type_ids: ScalarBuffer<i8>,
offsets: Option<ScalarBuffer<i32>>,
children: Vec<ArrayData>,
) -> Self {
Self {
data_type,
type_ids,
offsets,
children,
}
}
pub(crate) unsafe fn from_raw(builder: ArrayDataBuilder, mode: UnionMode) -> Self {
match mode {
UnionMode::Sparse => {
let type_ids = builder.buffers.into_iter().next().unwrap();
let type_ids = ScalarBuffer::new(type_ids, builder.offset, builder.len);
let children = builder
.child_data
.into_iter()
.map(|x| x.slice(builder.offset, builder.len))
.collect();
Self {
type_ids,
children,
data_type: builder.data_type,
offsets: None,
}
}
UnionMode::Dense => {
let mut iter = builder.buffers.into_iter();
let type_ids = iter.next().unwrap();
let offsets = iter.next().unwrap();
let type_ids = ScalarBuffer::new(type_ids, builder.offset, builder.len);
let offsets = ScalarBuffer::new(offsets, builder.offset, builder.len);
Self {
type_ids,
data_type: builder.data_type,
offsets: Some(offsets),
children: builder.child_data,
}
}
}
}
#[inline]
pub fn len(&self) -> usize {
self.type_ids.len()
}
#[inline]
pub fn type_ids(&self) -> &ScalarBuffer<i8> {
&self.type_ids
}
#[inline]
pub fn offsets(&self) -> Option<&ScalarBuffer<i32>> {
self.offsets.as_ref()
}
#[inline]
pub fn children(&self) -> &[ArrayData] {
&self.children
}
#[inline]
pub fn data_type(&self) -> &DataType {
&self.data_type
}
pub fn into_parts(
self,
) -> (
DataType,
ScalarBuffer<i8>,
Option<ScalarBuffer<i32>>,
Vec<ArrayData>,
) {
(self.data_type, self.type_ids, self.offsets, self.children)
}
pub fn slice(&self, offset: usize, len: usize) -> Self {
let (offsets, children) = match &self.offsets {
Some(offsets) => (Some(offsets.slice(offset, len)), self.children.clone()),
None => (
None,
self.children.iter().map(|c| c.slice(offset, len)).collect(),
),
};
Self {
data_type: self.data_type.clone(),
type_ids: self.type_ids.slice(offset, len),
offsets,
children,
}
}
pub(crate) fn layout(&self) -> ArrayDataLayout<'_> {
let buffers = match &self.offsets {
Some(offsets) => Buffers::two(self.type_ids.inner(), offsets.inner()),
None => Buffers::one(self.type_ids.inner()),
};
ArrayDataLayout {
data_type: &self.data_type,
len: self.type_ids.len(),
offset: 0,
nulls: None,
buffers,
child_data: &self.children,
}
}
}