use std::sync::Arc;
use polars::prelude::Series;
use crate::enums::error::MinarrowError;
use crate::ffi::arrow_c_ffi::{ArrowArray, ArrowSchema, export_to_c, import_from_c_owned};
use crate::ffi::arrow_dtype::ArrowType;
use crate::ffi::schema::Schema;
use crate::{Array, Field};
pub fn export(
array: Arc<Array>,
name: &str,
schema: Schema,
) -> Result<Series, MinarrowError> {
let field_dtype = schema.fields[0].dtype.clone();
let (c_arr, c_schema) = export_to_c(array, schema);
let arr_ptr = c_arr as *mut polars_arrow::ffi::ArrowArray;
let arr_val = unsafe { std::ptr::read(arr_ptr) };
unsafe {
drop(Box::from_raw(c_arr));
if let Some(release) = (*c_schema).release {
release(c_schema);
}
drop(Box::from_raw(c_schema));
}
let a2_dtype = arrow_type_to_polars_dtype(&field_dtype);
let a2_array = unsafe {
polars_arrow::ffi::import_array_from_c(arr_val, a2_dtype)
}
.map_err(|e| MinarrowError::BridgeError {
source: "polars_arrow",
message: format!("import_array_from_c: {e}"),
})?;
Ok(Series::from_arrow(name.into(), a2_array)?)
}
pub fn import_chunk(
name: &str,
nullable: bool,
arr2: Box<dyn polars_arrow::array::Array>,
) -> Result<(Arc<Array>, Field), MinarrowError> {
let dtype = arr2.dtype().clone();
let pa_arr = polars_arrow::ffi::export_array_to_c(arr2);
let pa_field =
polars_arrow::datatypes::Field::new(name.into(), dtype, nullable);
let pa_sch = polars_arrow::ffi::export_field_to_c(&pa_field);
let arr_ptr = Box::into_raw(Box::new(pa_arr)) as *mut ArrowArray;
let sch_ptr = Box::into_raw(Box::new(pa_sch)) as *mut ArrowSchema;
let arr_box = unsafe { Box::from_raw(arr_ptr) };
let sch_box = unsafe { Box::from_raw(sch_ptr) };
let (array, mut field) = unsafe { import_from_c_owned(arr_box, sch_box) };
field.name = name.to_string();
Ok((array, field))
}
fn arrow_type_to_polars_dtype(dtype: &ArrowType) -> polars_arrow::datatypes::ArrowDataType {
use crate::ffi::arrow_dtype::CategoricalIndexType;
match dtype {
ArrowType::Null => polars_arrow::datatypes::ArrowDataType::Null,
ArrowType::Boolean => polars_arrow::datatypes::ArrowDataType::Boolean,
#[cfg(feature = "extended_numeric_types")]
ArrowType::Int8 => polars_arrow::datatypes::ArrowDataType::Int8,
#[cfg(feature = "extended_numeric_types")]
ArrowType::Int16 => polars_arrow::datatypes::ArrowDataType::Int16,
ArrowType::Int32 => polars_arrow::datatypes::ArrowDataType::Int32,
ArrowType::Int64 => polars_arrow::datatypes::ArrowDataType::Int64,
#[cfg(feature = "extended_numeric_types")]
ArrowType::UInt8 => polars_arrow::datatypes::ArrowDataType::UInt8,
#[cfg(feature = "extended_numeric_types")]
ArrowType::UInt16 => polars_arrow::datatypes::ArrowDataType::UInt16,
ArrowType::UInt32 => polars_arrow::datatypes::ArrowDataType::UInt32,
ArrowType::UInt64 => polars_arrow::datatypes::ArrowDataType::UInt64,
ArrowType::Float32 => polars_arrow::datatypes::ArrowDataType::Float32,
ArrowType::Float64 => polars_arrow::datatypes::ArrowDataType::Float64,
ArrowType::String => polars_arrow::datatypes::ArrowDataType::Utf8,
#[cfg(feature = "large_string")]
ArrowType::LargeString => polars_arrow::datatypes::ArrowDataType::LargeUtf8,
ArrowType::Utf8View => polars_arrow::datatypes::ArrowDataType::Utf8,
#[cfg(feature = "datetime")]
ArrowType::Date32 => polars_arrow::datatypes::ArrowDataType::Date32,
#[cfg(feature = "datetime")]
ArrowType::Date64 => polars_arrow::datatypes::ArrowDataType::Date64,
#[cfg(feature = "datetime")]
ArrowType::Time32(u) => {
polars_arrow::datatypes::ArrowDataType::Time32(match u {
crate::TimeUnit::Seconds => polars_arrow::datatypes::TimeUnit::Second,
crate::TimeUnit::Milliseconds => {
polars_arrow::datatypes::TimeUnit::Millisecond
}
_ => panic!("Time32 supports Seconds or Milliseconds only"),
})
}
#[cfg(feature = "datetime")]
ArrowType::Time64(u) => {
polars_arrow::datatypes::ArrowDataType::Time64(match u {
crate::TimeUnit::Microseconds => {
polars_arrow::datatypes::TimeUnit::Microsecond
}
crate::TimeUnit::Nanoseconds => {
polars_arrow::datatypes::TimeUnit::Nanosecond
}
_ => panic!("Time64 supports Microseconds or Nanoseconds only"),
})
}
#[cfg(feature = "datetime")]
ArrowType::Duration32(u) => {
polars_arrow::datatypes::ArrowDataType::Duration(match u {
crate::TimeUnit::Seconds => polars_arrow::datatypes::TimeUnit::Second,
crate::TimeUnit::Milliseconds => {
polars_arrow::datatypes::TimeUnit::Millisecond
}
_ => panic!("Duration32 supports Seconds or Milliseconds only"),
})
}
#[cfg(feature = "datetime")]
ArrowType::Duration64(u) => {
polars_arrow::datatypes::ArrowDataType::Duration(match u {
crate::TimeUnit::Microseconds => {
polars_arrow::datatypes::TimeUnit::Microsecond
}
crate::TimeUnit::Nanoseconds => {
polars_arrow::datatypes::TimeUnit::Nanosecond
}
_ => panic!("Duration64 supports Microseconds or Nanoseconds only"),
})
}
#[cfg(feature = "datetime")]
ArrowType::Timestamp(u, tz) => polars_arrow::datatypes::ArrowDataType::Timestamp(
match u {
crate::TimeUnit::Seconds => polars_arrow::datatypes::TimeUnit::Second,
crate::TimeUnit::Milliseconds => {
polars_arrow::datatypes::TimeUnit::Millisecond
}
crate::TimeUnit::Microseconds => {
polars_arrow::datatypes::TimeUnit::Microsecond
}
crate::TimeUnit::Nanoseconds => {
polars_arrow::datatypes::TimeUnit::Nanosecond
}
crate::TimeUnit::Days => panic!("Timestamp(Days) is invalid"),
},
tz.as_ref().map(|s| s.as_str().into()),
),
#[cfg(feature = "datetime")]
ArrowType::Interval(iu) => {
polars_arrow::datatypes::ArrowDataType::Interval(match iu {
crate::IntervalUnit::YearMonth => {
polars_arrow::datatypes::IntervalUnit::YearMonth
}
crate::IntervalUnit::DaysTime => {
polars_arrow::datatypes::IntervalUnit::DayTime
}
crate::IntervalUnit::MonthDaysNs => {
polars_arrow::datatypes::IntervalUnit::MonthDayNano
}
})
}
ArrowType::Dictionary(idx) => {
let key: polars_arrow::datatypes::IntegerType = match idx {
#[cfg(feature = "default_categorical_8")]
CategoricalIndexType::UInt8 => {
polars_arrow::datatypes::IntegerType::UInt8
}
#[cfg(feature = "extended_categorical")]
CategoricalIndexType::UInt16 => {
polars_arrow::datatypes::IntegerType::UInt16
}
#[cfg(any(
not(feature = "default_categorical_8"),
feature = "extended_categorical"
))]
CategoricalIndexType::UInt32 => {
polars_arrow::datatypes::IntegerType::UInt32
}
#[cfg(feature = "extended_categorical")]
CategoricalIndexType::UInt64 => {
polars_arrow::datatypes::IntegerType::UInt64
}
};
polars_arrow::datatypes::ArrowDataType::Dictionary(
key,
Box::new(polars_arrow::datatypes::ArrowDataType::Utf8),
false,
)
}
}
}