dora_arrow_convert/
from_impls.rs1use arrow::{
2 array::{Array, AsArray, PrimitiveArray, StringArray},
3 datatypes::ArrowPrimitiveType,
4};
5use eyre::ContextCompat;
6
7use crate::ArrowData;
8
9impl From<ArrowData> for arrow::array::ArrayRef {
10 fn from(value: ArrowData) -> Self {
11 value.0
12 }
13}
14
15impl From<arrow::array::ArrayRef> for ArrowData {
16 fn from(value: arrow::array::ArrayRef) -> Self {
17 Self(value)
18 }
19}
20
21impl TryFrom<&ArrowData> for bool {
22 type Error = eyre::Report;
23 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
24 let bool_array = value.as_boolean_opt().context("not a bool array")?;
25 if bool_array.is_empty() {
26 eyre::bail!("empty array");
27 }
28 if bool_array.len() != 1 {
29 eyre::bail!("expected length 1");
30 }
31 if bool_array.null_count() != 0 {
32 eyre::bail!("bool array has nulls");
33 }
34 Ok(bool_array.value(0))
35 }
36}
37impl TryFrom<&ArrowData> for u8 {
38 type Error = eyre::Report;
39 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
40 let array = value
41 .as_primitive_opt::<arrow::datatypes::UInt8Type>()
42 .context("not a primitive UInt8Type array")?;
43 extract_single_primitive(array)
44 }
45}
46impl TryFrom<&ArrowData> for u16 {
47 type Error = eyre::Report;
48 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
49 let array = value
50 .as_primitive_opt::<arrow::datatypes::UInt16Type>()
51 .context("not a primitive UInt16Type array")?;
52 extract_single_primitive(array)
53 }
54}
55impl TryFrom<&ArrowData> for u32 {
56 type Error = eyre::Report;
57 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
58 let array = value
59 .as_primitive_opt::<arrow::datatypes::UInt32Type>()
60 .context("not a primitive UInt32Type array")?;
61 extract_single_primitive(array)
62 }
63}
64impl TryFrom<&ArrowData> for u64 {
65 type Error = eyre::Report;
66 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
67 let array = value
68 .as_primitive_opt::<arrow::datatypes::UInt64Type>()
69 .context("not a primitive UInt64Type array")?;
70 extract_single_primitive(array)
71 }
72}
73impl TryFrom<&ArrowData> for i8 {
74 type Error = eyre::Report;
75 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
76 let array = value
77 .as_primitive_opt::<arrow::datatypes::Int8Type>()
78 .context("not a primitive Int8Type array")?;
79 extract_single_primitive(array)
80 }
81}
82impl TryFrom<&ArrowData> for i16 {
83 type Error = eyre::Report;
84 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
85 let array = value
86 .as_primitive_opt::<arrow::datatypes::Int16Type>()
87 .context("not a primitive Int16Type array")?;
88 extract_single_primitive(array)
89 }
90}
91impl TryFrom<&ArrowData> for i32 {
92 type Error = eyre::Report;
93 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
94 let array = value
95 .as_primitive_opt::<arrow::datatypes::Int32Type>()
96 .context("not a primitive Int32Type array")?;
97 extract_single_primitive(array)
98 }
99}
100impl TryFrom<&ArrowData> for i64 {
101 type Error = eyre::Report;
102 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
103 let array = value
104 .as_primitive_opt::<arrow::datatypes::Int64Type>()
105 .context("not a primitive Int64Type array")?;
106 extract_single_primitive(array)
107 }
108}
109
110impl TryFrom<&ArrowData> for f32 {
111 type Error = eyre::Report;
112 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
113 let array = value
114 .as_primitive_opt::<arrow::datatypes::Float32Type>()
115 .context("not a primitive Float32Type array")?;
116 extract_single_primitive(array)
117 }
118}
119impl TryFrom<&ArrowData> for f64 {
120 type Error = eyre::Report;
121 fn try_from(value: &ArrowData) -> Result<Self, Self::Error> {
122 let array = value
123 .as_primitive_opt::<arrow::datatypes::Float64Type>()
124 .context("not a primitive Float64Type array")?;
125 extract_single_primitive(array)
126 }
127}
128
129impl<'a> TryFrom<&'a ArrowData> for &'a str {
130 type Error = eyre::Report;
131 fn try_from(value: &'a ArrowData) -> Result<Self, Self::Error> {
132 let array: &StringArray = value.as_string_opt().wrap_err("not a string array")?;
133 if array.is_empty() {
134 eyre::bail!("empty array");
135 }
136 if array.len() != 1 {
137 eyre::bail!("expected length 1");
138 }
139 if array.null_count() != 0 {
140 eyre::bail!("array has nulls");
141 }
142 Ok(array.value(0))
143 }
144}
145
146impl<'a> TryFrom<&'a ArrowData> for &'a [u8] {
147 type Error = eyre::Report;
148 fn try_from(value: &'a ArrowData) -> Result<Self, Self::Error> {
149 let array: &PrimitiveArray<arrow::datatypes::UInt8Type> = value
150 .as_primitive_opt()
151 .wrap_err("not a primitive UInt8Type array")?;
152 if array.null_count() != 0 {
153 eyre::bail!("array has nulls");
154 }
155 Ok(array.values())
156 }
157}
158
159impl<'a> TryFrom<&'a ArrowData> for Vec<u8> {
160 type Error = eyre::Report;
161 fn try_from(value: &'a ArrowData) -> Result<Self, Self::Error> {
162 value.try_into().map(|slice: &'a [u8]| slice.to_vec())
163 }
164}
165
166fn extract_single_primitive<T>(array: &PrimitiveArray<T>) -> Result<T::Native, eyre::Error>
167where
168 T: ArrowPrimitiveType,
169{
170 if array.is_empty() {
171 eyre::bail!("empty array");
172 }
173 if array.len() != 1 {
174 eyre::bail!("expected length 1");
175 }
176 if array.null_count() != 0 {
177 eyre::bail!("array has nulls");
178 }
179 Ok(array.value(0))
180}
181
182#[cfg(test)]
183mod tests {
184 use arrow::array::{make_array, PrimitiveArray};
185
186 use crate::ArrowData;
187
188 #[test]
189 fn test_u8() {
190 let array =
191 make_array(PrimitiveArray::<arrow::datatypes::UInt8Type>::from(vec![42]).into());
192 let data: ArrowData = array.into();
193 let value: u8 = (&data).try_into().unwrap();
194 assert_eq!(value, 42);
195 }
196}