use std::fmt;
use std::sync::Arc;
use std::{any::Any, convert::TryFrom};
use super::ArrayDataRef;
use super::*;
use crate::array::equal_json::JsonEqual;
use crate::error::Result;
use crate::ffi;
pub trait Array: fmt::Debug + Send + Sync + JsonEqual {
fn as_any(&self) -> &Any;
fn data(&self) -> ArrayDataRef;
fn data_ref(&self) -> &ArrayDataRef;
fn data_type(&self) -> &DataType {
self.data_ref().data_type()
}
fn slice(&self, offset: usize, length: usize) -> ArrayRef {
make_array(Arc::new(self.data_ref().as_ref().slice(offset, length)))
}
fn len(&self) -> usize {
self.data_ref().len()
}
fn is_empty(&self) -> bool {
self.data_ref().is_empty()
}
fn offset(&self) -> usize {
self.data_ref().offset()
}
fn is_null(&self, index: usize) -> bool {
self.data_ref().is_null(index)
}
fn is_valid(&self, index: usize) -> bool {
self.data_ref().is_valid(index)
}
fn null_count(&self) -> usize {
self.data_ref().null_count()
}
fn get_buffer_memory_size(&self) -> usize;
fn get_array_memory_size(&self) -> usize;
fn to_raw(
&self,
) -> Result<(*const ffi::FFI_ArrowArray, *const ffi::FFI_ArrowSchema)> {
let data = self.data().as_ref().clone();
let array = ffi::ArrowArray::try_from(data)?;
Ok(ffi::ArrowArray::into_raw(array))
}
}
pub type ArrayRef = Arc<Array>;
pub fn make_array(data: ArrayDataRef) -> ArrayRef {
match data.data_type() {
DataType::Boolean => Arc::new(BooleanArray::from(data)) as ArrayRef,
DataType::Int8 => Arc::new(Int8Array::from(data)) as ArrayRef,
DataType::Int16 => Arc::new(Int16Array::from(data)) as ArrayRef,
DataType::Int32 => Arc::new(Int32Array::from(data)) as ArrayRef,
DataType::Int64 => Arc::new(Int64Array::from(data)) as ArrayRef,
DataType::UInt8 => Arc::new(UInt8Array::from(data)) as ArrayRef,
DataType::UInt16 => Arc::new(UInt16Array::from(data)) as ArrayRef,
DataType::UInt32 => Arc::new(UInt32Array::from(data)) as ArrayRef,
DataType::UInt64 => Arc::new(UInt64Array::from(data)) as ArrayRef,
DataType::Float16 => panic!("Float16 datatype not supported"),
DataType::Float32 => Arc::new(Float32Array::from(data)) as ArrayRef,
DataType::Float64 => Arc::new(Float64Array::from(data)) as ArrayRef,
DataType::Date32(DateUnit::Day) => Arc::new(Date32Array::from(data)) as ArrayRef,
DataType::Date64(DateUnit::Millisecond) => {
Arc::new(Date64Array::from(data)) as ArrayRef
}
DataType::Time32(TimeUnit::Second) => {
Arc::new(Time32SecondArray::from(data)) as ArrayRef
}
DataType::Time32(TimeUnit::Millisecond) => {
Arc::new(Time32MillisecondArray::from(data)) as ArrayRef
}
DataType::Time64(TimeUnit::Microsecond) => {
Arc::new(Time64MicrosecondArray::from(data)) as ArrayRef
}
DataType::Time64(TimeUnit::Nanosecond) => {
Arc::new(Time64NanosecondArray::from(data)) as ArrayRef
}
DataType::Timestamp(TimeUnit::Second, _) => {
Arc::new(TimestampSecondArray::from(data)) as ArrayRef
}
DataType::Timestamp(TimeUnit::Millisecond, _) => {
Arc::new(TimestampMillisecondArray::from(data)) as ArrayRef
}
DataType::Timestamp(TimeUnit::Microsecond, _) => {
Arc::new(TimestampMicrosecondArray::from(data)) as ArrayRef
}
DataType::Timestamp(TimeUnit::Nanosecond, _) => {
Arc::new(TimestampNanosecondArray::from(data)) as ArrayRef
}
DataType::Interval(IntervalUnit::YearMonth) => {
Arc::new(IntervalYearMonthArray::from(data)) as ArrayRef
}
DataType::Interval(IntervalUnit::DayTime) => {
Arc::new(IntervalDayTimeArray::from(data)) as ArrayRef
}
DataType::Duration(TimeUnit::Second) => {
Arc::new(DurationSecondArray::from(data)) as ArrayRef
}
DataType::Duration(TimeUnit::Millisecond) => {
Arc::new(DurationMillisecondArray::from(data)) as ArrayRef
}
DataType::Duration(TimeUnit::Microsecond) => {
Arc::new(DurationMicrosecondArray::from(data)) as ArrayRef
}
DataType::Duration(TimeUnit::Nanosecond) => {
Arc::new(DurationNanosecondArray::from(data)) as ArrayRef
}
DataType::Binary => Arc::new(BinaryArray::from(data)) as ArrayRef,
DataType::LargeBinary => Arc::new(LargeBinaryArray::from(data)) as ArrayRef,
DataType::FixedSizeBinary(_) => {
Arc::new(FixedSizeBinaryArray::from(data)) as ArrayRef
}
DataType::Utf8 => Arc::new(StringArray::from(data)) as ArrayRef,
DataType::LargeUtf8 => Arc::new(LargeStringArray::from(data)) as ArrayRef,
DataType::List(_) => Arc::new(ListArray::from(data)) as ArrayRef,
DataType::LargeList(_) => Arc::new(LargeListArray::from(data)) as ArrayRef,
DataType::Struct(_) => Arc::new(StructArray::from(data)) as ArrayRef,
DataType::Union(_) => Arc::new(UnionArray::from(data)) as ArrayRef,
DataType::FixedSizeList(_, _) => {
Arc::new(FixedSizeListArray::from(data)) as ArrayRef
}
DataType::Dictionary(ref key_type, _) => match key_type.as_ref() {
DataType::Int8 => {
Arc::new(DictionaryArray::<Int8Type>::from(data)) as ArrayRef
}
DataType::Int16 => {
Arc::new(DictionaryArray::<Int16Type>::from(data)) as ArrayRef
}
DataType::Int32 => {
Arc::new(DictionaryArray::<Int32Type>::from(data)) as ArrayRef
}
DataType::Int64 => {
Arc::new(DictionaryArray::<Int64Type>::from(data)) as ArrayRef
}
DataType::UInt8 => {
Arc::new(DictionaryArray::<UInt8Type>::from(data)) as ArrayRef
}
DataType::UInt16 => {
Arc::new(DictionaryArray::<UInt16Type>::from(data)) as ArrayRef
}
DataType::UInt32 => {
Arc::new(DictionaryArray::<UInt32Type>::from(data)) as ArrayRef
}
DataType::UInt64 => {
Arc::new(DictionaryArray::<UInt64Type>::from(data)) as ArrayRef
}
dt => panic!("Unexpected dictionary key type {:?}", dt),
},
DataType::Null => Arc::new(NullArray::from(data)) as ArrayRef,
DataType::Decimal(_, _) => Arc::new(DecimalArray::from(data)) as ArrayRef,
dt => panic!("Unexpected data type {:?}", dt),
}
}
pub unsafe fn make_array_from_raw(
array: *const ffi::FFI_ArrowArray,
schema: *const ffi::FFI_ArrowSchema,
) -> Result<ArrayRef> {
let array = ffi::ArrowArray::try_from_raw(array, schema)?;
let data = Arc::new(ArrayData::try_from(array)?);
Ok(make_array(data))
}
pub(super) fn print_long_array<A, F>(
array: &A,
f: &mut fmt::Formatter,
print_item: F,
) -> fmt::Result
where
A: Array,
F: Fn(&A, usize, &mut fmt::Formatter) -> fmt::Result,
{
let head = std::cmp::min(10, array.len());
for i in 0..head {
if array.is_null(i) {
writeln!(f, " null,")?;
} else {
write!(f, " ")?;
print_item(&array, i, f)?;
writeln!(f, ",")?;
}
}
if array.len() > 10 {
if array.len() > 20 {
writeln!(f, " ...{} elements...,", array.len() - 20)?;
}
let tail = std::cmp::max(head, array.len() - 10);
for i in tail..array.len() {
if array.is_null(i) {
writeln!(f, " null,")?;
} else {
write!(f, " ")?;
print_item(&array, i, f)?;
writeln!(f, ",")?;
}
}
}
Ok(())
}