use crate::error::Result;
use polars::prelude::{DataFrame, Series};
use std::{mem, sync::Arc};
pub const POLARS_ARROW_FLAVOR: bool = false;
const IS_ARRAY_NULLABLE: bool = true;
pub fn convert_polars_df_schema_to_arrow_rb_schema(
polars_df_schema: polars::prelude::Schema,
) -> Result<Arc<arrow_schema::Schema>> {
let arrow_fields: Result<Vec<arrow_schema::Field>> = polars_df_schema
.into_iter()
.map(|(name, df_dtype)| {
let polars_arrow_dtype = df_dtype.to_arrow(POLARS_ARROW_FLAVOR);
let polars_field =
polars_arrow::datatypes::Field::new(name, polars_arrow_dtype, IS_ARRAY_NULLABLE);
convert_polars_arrow_field_to_arrow_rs_field(polars_field)
})
.collect();
Ok(Arc::new(arrow_schema::Schema::new(arrow_fields?)))
}
pub fn convert_arrow_rb_schema_to_polars_df_schema(
arrow_schema: &arrow_schema::Schema,
) -> Result<polars::prelude::Schema> {
let polars_df_fields: Result<Vec<polars::prelude::Field>> = arrow_schema
.fields()
.iter()
.map(|arrow_rs_field| {
let polars_arrow_field = convert_arrow_rs_field_to_polars_arrow_field(arrow_rs_field)?;
Ok(polars::prelude::Field::new(
arrow_rs_field.name(),
polars::datatypes::DataType::from(polars_arrow_field.data_type()),
))
})
.collect();
Ok(polars::prelude::Schema::from_iter(polars_df_fields?))
}
pub fn convert_arrow_rb_to_polars_df(
arrow_rb: &arrow::record_batch::RecordBatch,
polars_schema: &polars::prelude::Schema,
) -> Result<DataFrame> {
let mut columns: Vec<Series> = Vec::with_capacity(arrow_rb.num_columns());
for (i, column) in arrow_rb.columns().iter().enumerate() {
let polars_df_dtype = polars_schema.try_get_at_index(i)?.1;
let polars_arrow_dtype = polars_df_dtype.to_arrow(POLARS_ARROW_FLAVOR);
let polars_array =
convert_arrow_rs_array_to_polars_arrow_array(column, polars_arrow_dtype)?;
columns.push(Series::from_arrow(
polars_schema.try_get_at_index(i)?.0,
polars_array,
)?);
}
Ok(DataFrame::from_iter(columns))
}
pub fn convert_polars_arrow_array_to_arrow_rs_array(
polars_array: Box<dyn polars_arrow::array::Array>,
arrow_datatype: arrow_schema::DataType,
) -> std::result::Result<arrow_array::ArrayRef, arrow_schema::ArrowError> {
let polars_c_array = polars_arrow::ffi::export_array_to_c(polars_array);
let arrow_c_array: arrow_data::ffi::FFI_ArrowArray = unsafe { mem::transmute(polars_c_array) };
Ok(arrow_array::make_array(unsafe {
arrow::ffi::from_ffi_and_data_type(arrow_c_array, arrow_datatype)
}?))
}
fn convert_arrow_rs_array_to_polars_arrow_array(
arrow_rs_array: &Arc<dyn arrow_array::Array>,
polars_arrow_dtype: polars::datatypes::ArrowDataType,
) -> Result<Box<dyn polars_arrow::array::Array>> {
let arrow_c_array = arrow::ffi::FFI_ArrowArray::new(&arrow_rs_array.to_data());
let polars_c_array: polars_arrow::ffi::ArrowArray = unsafe { mem::transmute(arrow_c_array) };
Ok(unsafe { polars_arrow::ffi::import_array_from_c(polars_c_array, polars_arrow_dtype) }?)
}
fn convert_polars_arrow_field_to_arrow_rs_field(
polars_arrow_field: polars_arrow::datatypes::Field,
) -> Result<arrow_schema::Field> {
let polars_c_schema = polars_arrow::ffi::export_field_to_c(&polars_arrow_field);
let arrow_c_schema: arrow::ffi::FFI_ArrowSchema =
unsafe { mem::transmute::<_, _>(polars_c_schema) };
let arrow_rs_dtype = arrow_schema::DataType::try_from(&arrow_c_schema)?;
Ok(arrow_schema::Field::new(
polars_arrow_field.name,
arrow_rs_dtype,
IS_ARRAY_NULLABLE,
))
}
fn convert_arrow_rs_field_to_polars_arrow_field(
arrow_rs_field: &arrow_schema::Field,
) -> Result<polars_arrow::datatypes::Field> {
let arrow_rs_dtype = arrow_rs_field.data_type();
let arrow_c_schema = arrow::ffi::FFI_ArrowSchema::try_from(arrow_rs_dtype)?;
let polars_c_schema: polars_arrow::ffi::ArrowSchema =
unsafe { mem::transmute::<_, _>(arrow_c_schema) };
Ok(unsafe { polars_arrow::ffi::import_field_from_c(&polars_c_schema) }?)
}