1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use crate::{array::FromFfi, error::Result, ffi};

use super::super::{ffi::ToFfi, Array};
use super::UnionArray;

unsafe impl ToFfi for UnionArray {
    fn buffers(&self) -> Vec<Option<*const u8>> {
        if let Some(offsets) = &self.offsets {
            vec![
                Some(self.types.as_ptr().cast::<u8>()),
                Some(offsets.as_ptr().cast::<u8>()),
            ]
        } else {
            vec![Some(self.types.as_ptr().cast::<u8>())]
        }
    }

    fn children(&self) -> Vec<Box<dyn Array>> {
        self.fields.clone()
    }

    fn offset(&self) -> Option<usize> {
        Some(self.types.offset())
    }

    fn to_ffi_aligned(&self) -> Self {
        self.clone()
    }
}

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

        let mut types = unsafe { array.buffer::<i8>(0) }?;
        let offsets = if Self::is_sparse(&data_type) {
            None
        } else {
            Some(unsafe { array.buffer::<i32>(1) }?)
        };

        let length = array.array().len();
        let offset = array.array().offset();
        let fields = (0..fields.len())
            .map(|index| {
                let child = array.child(index)?;
                ffi::try_from(child)
            })
            .collect::<Result<Vec<Box<dyn Array>>>>()?;

        if offset > 0 {
            types.slice(offset, length);
        };

        Self::try_new(data_type, types, fields, offsets)
    }
}