Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Simplified ffi.
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgecarleitao committed Aug 23, 2021
1 parent 6b687d2 commit 6b9ee21
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 95 deletions.
2 changes: 1 addition & 1 deletion src/array/binary/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ unsafe impl<O: Offset> ToFfi for BinaryArray<O> {

unsafe impl<O: Offset, A: ffi::ArrowArrayRef> FromFfi<A> for BinaryArray<O> {
fn try_from_ffi(array: A) -> Result<Self> {
let data_type = array.field()?.data_type().clone();
let data_type = array.field().data_type().clone();
let expected = if O::is_large() {
DataType::LargeBinary
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/array/boolean/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ unsafe impl ToFfi for BooleanArray {

unsafe impl<A: ffi::ArrowArrayRef> FromFfi<A> for BooleanArray {
fn try_from_ffi(array: A) -> Result<Self> {
let data_type = array.field()?.data_type().clone();
let data_type = array.field().data_type().clone();
assert_eq!(data_type, DataType::Boolean);
let length = array.array().len();
let offset = array.array().offset();
Expand Down
2 changes: 1 addition & 1 deletion src/array/list/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ unsafe impl<O: Offset> ToFfi for ListArray<O> {

unsafe impl<O: Offset, A: ffi::ArrowArrayRef> FromFfi<A> for ListArray<O> {
fn try_from_ffi(array: A) -> Result<Self> {
let data_type = array.field()?.data_type().clone();
let data_type = array.field().data_type().clone();
let length = array.array().len();
let offset = array.array().offset();
let mut validity = unsafe { array.validity() }?;
Expand Down
2 changes: 1 addition & 1 deletion src/array/primitive/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ unsafe impl<T: NativeType> ToFfi for PrimitiveArray<T> {

unsafe impl<T: NativeType, A: ffi::ArrowArrayRef> FromFfi<A> for PrimitiveArray<T> {
fn try_from_ffi(array: A) -> Result<Self> {
let data_type = array.field()?.data_type().clone();
let data_type = array.field().data_type().clone();
let length = array.array().len();
let offset = array.array().offset();
let mut validity = unsafe { array.validity() }?;
Expand Down
2 changes: 1 addition & 1 deletion src/array/struct_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ unsafe impl ToFfi for StructArray {

unsafe impl<A: ffi::ArrowArrayRef> FromFfi<A> for StructArray {
fn try_from_ffi(array: A) -> Result<Self> {
let field = array.field()?;
let field = array.field();
let fields = Self::get_fields(field.data_type()).to_vec();

let length = array.array().len();
Expand Down
2 changes: 1 addition & 1 deletion src/array/union/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ unsafe impl ToFfi for UnionArray {

unsafe impl<A: ffi::ArrowArrayRef> FromFfi<A> for UnionArray {
fn try_from_ffi(array: A) -> Result<Self> {
let field = array.field()?;
let field = array.field();
let data_type = field.data_type().clone();
let fields = Self::get_fields(field.data_type());

Expand Down
3 changes: 1 addition & 2 deletions src/ffi/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ use crate::{
/// * the data type is not supported
/// * the interface is not valid (e.g. a null pointer)
pub fn try_from<A: ArrowArrayRef>(array: A) -> Result<Box<dyn Array>> {
let field = array.field()?;
let array: Box<dyn Array> = match field.data_type() {
let array: Box<dyn Array> = match array.field().data_type() {
DataType::Boolean => Box::new(BooleanArray::try_from_ffi(array)?),
DataType::Int8 => Box::new(PrimitiveArray::<i8>::try_from_ffi(array)?),
DataType::Int16 => Box::new(PrimitiveArray::<i16>::try_from_ffi(array)?),
Expand Down
100 changes: 30 additions & 70 deletions src/ffi/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

use std::{ptr::NonNull, sync::Arc};

use super::schema::{to_field, Ffi_ArrowSchema};
use crate::{
array::{buffers_children_dictionary, Array},
bitmap::{utils::bytes_for, Bitmap},
Expand All @@ -27,6 +26,7 @@ use crate::{
},
datatypes::{DataType, Field},
error::{ArrowError, Result},
ffi::schema::get_field_child,
types::NativeType,
};

Expand Down Expand Up @@ -95,7 +95,8 @@ impl Ffi_ArrowArray {
/// # Safety
/// This method releases `buffers`. Consumers of this struct *must* call `release` before
/// releasing this struct, or contents in `buffers` leak.
fn new(array: Arc<dyn Array>) -> Self {
pub fn new(array: Arc<dyn Array>) -> Self {
println!("{:?}", array);
let (buffers, children, dictionary) = buffers_children_dictionary(array.as_ref());

let buffers_ptr = buffers
Expand All @@ -114,6 +115,7 @@ impl Ffi_ArrowArray {
.collect::<Box<_>>();
let n_children = children_ptr.len() as i64;

println!("{:?}", dictionary);
let dictionary_ptr =
dictionary.map(|array| Box::into_raw(Box::new(Ffi_ArrowArray::new(array))));

Expand Down Expand Up @@ -283,31 +285,32 @@ fn buffer_len(array: &Ffi_ArrowArray, data_type: &DataType, i: usize) -> Result<

fn create_child(
array: &Ffi_ArrowArray,
schema: &Ffi_ArrowSchema,
field: &Field,
parent: Arc<ArrowArray>,
index: usize,
) -> Result<ArrowArrayChild<'static>> {
let field = get_field_child(field, index)?;
assert!(index < array.n_children as usize);
assert!(!array.children.is_null());
unsafe {
let arr_ptr = *array.children.add(index);
let schema_ptr = schema.child(index);
assert!(!arr_ptr.is_null());
let arr_ptr = &*arr_ptr;
Ok(ArrowArrayChild::from_raw(arr_ptr, schema_ptr, parent))

Ok(ArrowArrayChild::from_raw(arr_ptr, field, parent))
}
}

fn create_dictionary(
array: &Ffi_ArrowArray,
schema: &Ffi_ArrowSchema,
field: &Field,
parent: Arc<ArrowArray>,
) -> Result<Option<ArrowArrayChild<'static>>> {
let schema = schema.dictionary();
if let Some(schema) = schema {
if let DataType::Dictionary(_, values) = field.data_type() {
let field = Field::new("", values.as_ref().clone(), true);
assert!(!array.dictionary.is_null());
let array = unsafe { &*array.dictionary };
Ok(Some(ArrowArrayChild::from_raw(array, schema, parent)))
Ok(Some(ArrowArrayChild::from_raw(array, field, parent)))
} else {
Ok(None)
}
Expand Down Expand Up @@ -339,7 +342,7 @@ pub trait ArrowArrayRef {
// +1 to ignore null bitmap
create_buffer::<T>(
self.array(),
self.field()?.data_type(),
self.field().data_type(),
self.deallocation(),
index + 1,
)
Expand All @@ -354,17 +357,16 @@ pub trait ArrowArrayRef {
}

fn child(&self, index: usize) -> Result<ArrowArrayChild> {
create_child(self.array(), self.schema(), self.parent().clone(), index)
create_child(self.array(), self.field(), self.parent().clone(), index)
}

fn dictionary(&self) -> Result<Option<ArrowArrayChild>> {
create_dictionary(self.array(), self.schema(), self.parent().clone())
create_dictionary(self.array(), self.field(), self.parent().clone())
}

fn parent(&self) -> &Arc<ArrowArray>;
fn array(&self) -> &Ffi_ArrowArray;
fn schema(&self) -> &Ffi_ArrowSchema;
fn field(&self) -> Result<Field>;
fn field(&self) -> &Field;
}

/// Struct used to move an Array from and to the C Data Interface.
Expand All @@ -389,13 +391,19 @@ pub trait ArrowArrayRef {
#[derive(Debug)]
pub struct ArrowArray {
array: Arc<Ffi_ArrowArray>,
schema: Arc<Ffi_ArrowSchema>,
field: Field,
}

impl ArrowArray {
pub fn new(array: Arc<Ffi_ArrowArray>, field: Field) -> Self {
Self { array, field }
}
}

impl ArrowArrayRef for Arc<ArrowArray> {
/// the data_type as declared in the schema
fn field(&self) -> Result<Field> {
to_field(&self.schema)
fn field(&self) -> &Field {
&self.field
}

fn parent(&self) -> &Arc<ArrowArray> {
Expand All @@ -405,23 +413,19 @@ impl ArrowArrayRef for Arc<ArrowArray> {
fn array(&self) -> &Ffi_ArrowArray {
self.array.as_ref()
}

fn schema(&self) -> &Ffi_ArrowSchema {
self.schema.as_ref()
}
}

#[derive(Debug)]
pub struct ArrowArrayChild<'a> {
array: &'a Ffi_ArrowArray,
schema: &'a Ffi_ArrowSchema,
field: Field,
parent: Arc<ArrowArray>,
}

impl<'a> ArrowArrayRef for ArrowArrayChild<'a> {
/// the data_type as declared in the schema
fn field(&self) -> Result<Field> {
to_field(self.schema)
fn field(&self) -> &Field {
&self.field
}

fn parent(&self) -> &Arc<ArrowArray> {
Expand All @@ -431,58 +435,14 @@ impl<'a> ArrowArrayRef for ArrowArrayChild<'a> {
fn array(&self) -> &Ffi_ArrowArray {
self.array
}

fn schema(&self) -> &Ffi_ArrowSchema {
self.schema
}
}

impl<'a> ArrowArrayChild<'a> {
fn from_raw(
array: &'a Ffi_ArrowArray,
schema: &'a Ffi_ArrowSchema,
parent: Arc<ArrowArray>,
) -> Self {
fn from_raw(array: &'a Ffi_ArrowArray, field: Field, parent: Arc<ArrowArray>) -> Self {
Self {
array,
schema,
field,
parent,
}
}
}

/// Exports an `Array` to the C data interface.
pub fn export_array_to_c(array: Arc<dyn Array>) -> Result<ArrowArray> {
let field = Field::new("", array.data_type().clone(), array.null_count() != 0);

Ok(ArrowArray {
array: Arc::new(Ffi_ArrowArray::new(array)),
schema: Arc::new(Ffi_ArrowSchema::new(&field)),
})
}

/// Exports a [`Field`] to the C data interface.
pub fn export_field_to_c(field: &Field) -> Arc<Ffi_ArrowSchema> {
Arc::new(Ffi_ArrowSchema::new(field))
}

/// Imports a [`Field`] from the C data interface.
pub fn import_field_from_c(field: &Ffi_ArrowSchema) -> Result<Field> {
to_field(field)
}

pub fn create_empty() -> ArrowArray {
ArrowArray {
array: Arc::new(Ffi_ArrowArray::empty()),
schema: Arc::new(Ffi_ArrowSchema::empty()),
}
}

impl ArrowArray {
pub fn references(&self) -> (*mut Ffi_ArrowArray, *mut Ffi_ArrowSchema) {
(
self.array.as_ref() as *const Ffi_ArrowArray as *mut Ffi_ArrowArray,
self.schema.as_ref() as *const Ffi_ArrowSchema as *mut Ffi_ArrowSchema,
)
}
}
36 changes: 32 additions & 4 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,35 @@ mod ffi;
mod schema;

pub use array::try_from;
pub use ffi::{
create_empty, export_array_to_c, export_field_to_c, import_field_from_c, ArrowArray,
ArrowArrayRef,
};
pub use ffi::{ArrowArray, ArrowArrayRef};

use std::sync::Arc;

use crate::array::Array;
use crate::datatypes::Field;
use crate::error::Result;

use ffi::*;
use schema::Ffi_ArrowSchema;

use self::schema::to_field;

/// Exports an `Array` to the C data interface.
pub fn export_array_to_c(array: Arc<dyn Array>) -> Arc<Ffi_ArrowArray> {
Arc::new(Ffi_ArrowArray::new(array))
}

/// Exports a [`Field`] to the C data interface.
pub fn export_field_to_c(field: &Field) -> Arc<Ffi_ArrowSchema> {
Arc::new(Ffi_ArrowSchema::new(field))
}

/// Imports a [`Field`] from the C data interface.
pub fn import_field_from_c(field: &Ffi_ArrowSchema) -> Result<Field> {
to_field(field)
}

/// Imports a [`Field`] from the C data interface.
pub fn import_array_from_c(array: Arc<Ffi_ArrowArray>, field: &Field) -> Result<Box<dyn Array>> {
try_from(Arc::new(ArrowArray::new(array, field.clone())))
}
22 changes: 19 additions & 3 deletions src/ffi/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Ffi_ArrowSchema {

let dictionary = if let DataType::Dictionary(_, values) = field.data_type() {
// we do not store field info in the dict values, so can't recover it all :(
let field = Field::new("item", values.as_ref().clone(), true);
let field = Field::new("", values.as_ref().clone(), true);
Some(Box::new(Ffi_ArrowSchema::new(&field)))
} else {
None
Expand Down Expand Up @@ -172,8 +172,11 @@ pub fn to_field(schema: &Ffi_ArrowSchema) -> Result<Field> {
let dictionary = schema.dictionary();
let data_type = if let Some(dictionary) = dictionary {
let indices_data_type = to_data_type(schema)?;
let values_data_type = to_data_type(dictionary)?;
DataType::Dictionary(Box::new(indices_data_type), Box::new(values_data_type))
let values = to_field(dictionary)?;
DataType::Dictionary(
Box::new(indices_data_type),
Box::new(values.data_type().clone()),
)
} else {
to_data_type(schema)?
};
Expand Down Expand Up @@ -355,3 +358,16 @@ fn to_format(data_type: &DataType) -> String {
DataType::Dictionary(index, _) => to_format(index.as_ref()),
}
}

pub(super) fn get_field_child(field: &Field, index: usize) -> Result<Field> {
match (index, field.data_type()) {
(0, DataType::List(field)) => Ok(field.as_ref().clone()),
(0, DataType::LargeList(field)) => Ok(field.as_ref().clone()),
(index, DataType::Struct(fields)) => Ok(fields[index].clone()),
(index, DataType::Union(fields, _, _)) => Ok(fields[index].clone()),
(child, data_type) => Err(ArrowError::Ffi(format!(
"Requested child {} to type {:?} that has no such child",
child, data_type
))),
}
}
Loading

0 comments on commit 6b9ee21

Please sign in to comment.