dora_core/
metadata.rs

1use dora_message::{
2    arrow_data::ArrayData,
3    arrow_schema::DataType,
4    metadata::{ArrowTypeInfo, BufferOffset},
5};
6use eyre::Context;
7
8pub trait ArrowTypeInfoExt {
9    fn empty() -> Self;
10    fn byte_array(data_len: usize) -> Self;
11    unsafe fn from_array(
12        array: &ArrayData,
13        region_start: *const u8,
14        region_len: usize,
15    ) -> eyre::Result<Self>
16    where
17        Self: Sized;
18}
19
20impl ArrowTypeInfoExt for ArrowTypeInfo {
21    fn empty() -> Self {
22        Self {
23            data_type: DataType::Null,
24            len: 0,
25            null_count: 0,
26            validity: None,
27            offset: 0,
28            buffer_offsets: Vec::new(),
29            child_data: Vec::new(),
30        }
31    }
32
33    fn byte_array(data_len: usize) -> Self {
34        Self {
35            data_type: DataType::UInt8,
36            len: data_len,
37            null_count: 0,
38            validity: None,
39            offset: 0,
40            buffer_offsets: vec![BufferOffset {
41                offset: 0,
42                len: data_len,
43            }],
44            child_data: Vec::new(),
45        }
46    }
47
48    unsafe fn from_array(
49        array: &ArrayData,
50        region_start: *const u8,
51        region_len: usize,
52    ) -> eyre::Result<Self> {
53        Ok(Self {
54            data_type: array.data_type().clone(),
55            len: array.len(),
56            null_count: array.null_count(),
57            validity: array.nulls().map(|b| b.validity().to_owned()),
58            offset: array.offset(),
59            buffer_offsets: array
60                .buffers()
61                .iter()
62                .map(|b| {
63                    let ptr = b.as_ptr();
64                    if ptr as usize <= region_start as usize {
65                        eyre::bail!("ptr {ptr:p} starts before region {region_start:p}");
66                    }
67                    if ptr as usize >= region_start as usize + region_len {
68                        eyre::bail!("ptr {ptr:p} starts after region {region_start:p}");
69                    }
70                    if ptr as usize + b.len() > region_start as usize + region_len {
71                        eyre::bail!("ptr {ptr:p} ends after region {region_start:p}");
72                    }
73                    let offset = usize::try_from(unsafe { ptr.offset_from(region_start) })
74                        .context("offset_from is negative")?;
75
76                    Result::<_, eyre::Report>::Ok(BufferOffset {
77                        offset,
78                        len: b.len(),
79                    })
80                })
81                .collect::<Result<_, _>>()?,
82            child_data: array
83                .child_data()
84                .iter()
85                .map(|c| unsafe { Self::from_array(c, region_start, region_len) })
86                .collect::<Result<_, _>>()?,
87        })
88    }
89}