Skip to main content

polars_arrow/array/
ffi.rs

1use crate::array::*;
2use crate::datatypes::PhysicalType;
3use crate::ffi;
4
5/// Trait describing how a struct presents itself to the
6/// [C data interface](https://arrow.apache.org/docs/format/CDataInterface.html) (FFI).
7/// # Safety
8/// Implementing this trait incorrect will lead to UB
9pub(crate) unsafe trait ToFfi {
10    /// The pointers to the buffers.
11    fn buffers(&self) -> Vec<Option<*const u8>>;
12
13    /// The children
14    fn children(&self) -> Vec<Box<dyn Array>> {
15        vec![]
16    }
17
18    /// The offset
19    fn offset(&self) -> Option<usize>;
20
21    /// return a partial clone of self with an offset.
22    fn to_ffi_aligned(&self) -> Self;
23}
24
25/// Trait describing how a struct imports into itself from the
26/// [C data interface](https://arrow.apache.org/docs/format/CDataInterface.html) (FFI).
27pub(crate) trait FromFfi<T: ffi::ArrowArrayRef>: Sized {
28    /// Convert itself from FFI.
29    ///
30    /// # Safety
31    /// This function is intrinsically `unsafe` as it requires the FFI to be made according
32    /// to the [C data interface](https://arrow.apache.org/docs/format/CDataInterface.html)
33    unsafe fn try_from_ffi(array: T) -> PolarsResult<Self>;
34}
35
36macro_rules! ffi_dyn {
37    ($array:expr, $ty:ty) => {{
38        let array = $array.as_any().downcast_ref::<$ty>().unwrap();
39
40        (
41            array.offset().unwrap(),
42            array.buffers(),
43            array.children(),
44            None,
45        )
46    }};
47}
48
49type BuffersChildren = (
50    usize,
51    Vec<Option<*const u8>>,
52    Vec<Box<dyn Array>>,
53    Option<Box<dyn Array>>,
54);
55
56pub fn offset_buffers_children_dictionary(array: &dyn Array) -> BuffersChildren {
57    use PhysicalType::*;
58
59    match array.dtype().to_physical_type() {
60        Null => ffi_dyn!(array, NullArray),
61        Boolean => ffi_dyn!(array, BooleanArray),
62        Primitive(primitive) => with_match_primitive_type_full!(primitive, |$T| {
63            ffi_dyn!(array, PrimitiveArray<$T>)
64        }),
65        Binary => ffi_dyn!(array, BinaryArray<i32>),
66        LargeBinary => ffi_dyn!(array, BinaryArray<i64>),
67        FixedSizeBinary => ffi_dyn!(array, FixedSizeBinaryArray),
68        Utf8 => ffi_dyn!(array, Utf8Array::<i32>),
69        LargeUtf8 => ffi_dyn!(array, Utf8Array::<i64>),
70        List => ffi_dyn!(array, ListArray::<i32>),
71        LargeList => ffi_dyn!(array, ListArray::<i64>),
72        FixedSizeList => ffi_dyn!(array, FixedSizeListArray),
73        Struct => ffi_dyn!(array, StructArray),
74        Union => ffi_dyn!(array, UnionArray),
75        Map => ffi_dyn!(array, MapArray),
76        BinaryView => ffi_dyn!(array, BinaryViewArray),
77        Utf8View => ffi_dyn!(array, Utf8ViewArray),
78        Dictionary(key_type) => {
79            match_integer_type!(key_type, |$T| {
80                let array = array.as_any().downcast_ref::<DictionaryArray<$T>>().unwrap();
81                (
82                    array.offset().unwrap(),
83                    array.buffers(),
84                    array.children(),
85                    Some(array.values().clone()),
86                )
87            })
88        },
89    }
90}