use arrow::array::{Array, ArrayRef};
use arrow::datatypes::DataType;
use crate::datatype::{ColumnError, InfallibleBuild, LogicalType, RefType, downcast_array};
pub struct Binary;
pub struct LargeBinary;
pub struct BinaryView;
macro_rules! impl_binary_datatype {
($marker:ty, $array:ty, $datatype:expr) => {
impl LogicalType for $marker {
type Typed = $array;
type Value<'a> = &'a [u8];
type Owned = Vec<u8>;
fn downcast(array: &dyn Array) -> Result<Self::Typed, ColumnError> {
downcast_array::<$array>(array, || format!("{:?}", $datatype))
}
#[inline]
fn is_null(typed: &Self::Typed, index: usize) -> bool {
typed.is_null(index)
}
#[inline]
unsafe fn is_null_unchecked(typed: &Self::Typed, index: usize) -> bool {
unsafe { crate::datatype::leaf_is_null_unchecked(typed, index) }
}
#[inline]
fn value(typed: &Self::Typed, index: usize) -> Self::Value<'_> {
typed.value(index)
}
#[inline]
unsafe fn value_unchecked(typed: &Self::Typed, index: usize) -> Self::Value<'_> {
unsafe { typed.value_unchecked(index) }
}
fn to_owned_value(value: Self::Value<'_>) -> Self::Owned {
value.to_vec()
}
}
impl crate::ConcreteType for $marker {
fn datatype() -> DataType {
$datatype
}
fn build(
values: impl Iterator<Item = Option<Self::Owned>>,
) -> Result<ArrayRef, ColumnError> {
Ok(std::sync::Arc::new(<$array>::from_iter(values)))
}
}
impl InfallibleBuild for $marker {}
impl RefType for $marker {
type Ref = [u8];
fn value_ref(typed: &Self::Typed, index: usize) -> &[u8] {
typed.value(index)
}
}
};
}
impl_binary_datatype!(Binary, arrow::array::BinaryArray, DataType::Binary);
impl_binary_datatype!(
LargeBinary,
arrow::array::LargeBinaryArray,
DataType::LargeBinary
);
impl_binary_datatype!(
BinaryView,
arrow::array::BinaryViewArray,
DataType::BinaryView
);
pub struct AnyBinary;
#[derive(Clone)]
pub enum AnyTypedBinary {
Binary(arrow::array::BinaryArray),
LargeBinary(arrow::array::LargeBinaryArray),
BinaryView(arrow::array::BinaryViewArray),
FixedSizeBinary(arrow::array::FixedSizeBinaryArray),
}
impl LogicalType for AnyBinary {
type Typed = AnyTypedBinary;
type Value<'a> = &'a [u8];
type Owned = Vec<u8>;
fn downcast(array: &dyn Array) -> Result<Self::Typed, ColumnError> {
match array.data_type() {
DataType::Binary => Ok(AnyTypedBinary::Binary(downcast_array(array, || {
"Binary".to_owned()
})?)),
DataType::LargeBinary => {
Ok(AnyTypedBinary::LargeBinary(downcast_array(array, || {
"LargeBinary".to_owned()
})?))
}
DataType::BinaryView => Ok(AnyTypedBinary::BinaryView(downcast_array(array, || {
"BinaryView".to_owned()
})?)),
DataType::FixedSizeBinary(_) => Ok(AnyTypedBinary::FixedSizeBinary(downcast_array(
array,
|| "FixedSizeBinary".to_owned(),
)?)),
actual => Err(ColumnError::WrongDatatype {
expected: "a binary array (Binary/LargeBinary/BinaryView/FixedSizeBinary)"
.to_owned(),
actual: actual.clone(),
}),
}
}
#[inline]
fn is_null(typed: &Self::Typed, index: usize) -> bool {
match typed {
AnyTypedBinary::Binary(array) => array.is_null(index),
AnyTypedBinary::LargeBinary(array) => array.is_null(index),
AnyTypedBinary::BinaryView(array) => array.is_null(index),
AnyTypedBinary::FixedSizeBinary(array) => array.is_null(index),
}
}
#[inline]
unsafe fn is_null_unchecked(typed: &Self::Typed, index: usize) -> bool {
unsafe {
match typed {
AnyTypedBinary::Binary(array) => {
crate::datatype::leaf_is_null_unchecked(array, index)
}
AnyTypedBinary::LargeBinary(array) => {
crate::datatype::leaf_is_null_unchecked(array, index)
}
AnyTypedBinary::BinaryView(array) => {
crate::datatype::leaf_is_null_unchecked(array, index)
}
AnyTypedBinary::FixedSizeBinary(array) => {
crate::datatype::leaf_is_null_unchecked(array, index)
}
}
}
}
#[inline]
fn value(typed: &Self::Typed, index: usize) -> Self::Value<'_> {
match typed {
AnyTypedBinary::Binary(array) => array.value(index),
AnyTypedBinary::LargeBinary(array) => array.value(index),
AnyTypedBinary::BinaryView(array) => array.value(index),
AnyTypedBinary::FixedSizeBinary(array) => array.value(index),
}
}
#[inline]
unsafe fn value_unchecked(typed: &Self::Typed, index: usize) -> Self::Value<'_> {
unsafe {
match typed {
AnyTypedBinary::Binary(array) => array.value_unchecked(index),
AnyTypedBinary::LargeBinary(array) => array.value_unchecked(index),
AnyTypedBinary::BinaryView(array) => array.value_unchecked(index),
AnyTypedBinary::FixedSizeBinary(array) => array.value_unchecked(index),
}
}
}
fn to_owned_value(value: Self::Value<'_>) -> Self::Owned {
value.to_vec()
}
}
impl RefType for AnyBinary {
type Ref = [u8];
#[inline]
fn value_ref(typed: &Self::Typed, index: usize) -> &[u8] {
Self::value(typed, index)
}
}