typed_arrow/bridge/
binary.rs

1//! Binary family bindings (Binary, `LargeBinary`, `FixedSizeBinary`).
2
3use arrow_array::{
4    Array, FixedSizeBinaryArray, LargeBinaryArray,
5    builder::{BinaryBuilder, FixedSizeBinaryBuilder, LargeBinaryBuilder},
6};
7use arrow_schema::DataType;
8
9use super::ArrowBinding;
10#[cfg(feature = "views")]
11use super::ArrowBindingView;
12
13// Binary / Vec<u8>
14impl ArrowBinding for Vec<u8> {
15    type Builder = BinaryBuilder;
16    type Array = arrow_array::BinaryArray;
17    fn data_type() -> DataType {
18        DataType::Binary
19    }
20    fn new_builder(capacity: usize) -> Self::Builder {
21        BinaryBuilder::with_capacity(capacity, 0)
22    }
23    fn append_value(b: &mut Self::Builder, v: &Self) {
24        b.append_value(v.as_slice());
25    }
26    fn append_null(b: &mut Self::Builder) {
27        b.append_null();
28    }
29    fn finish(mut b: Self::Builder) -> Self::Array {
30        b.finish()
31    }
32}
33
34#[cfg(feature = "views")]
35impl ArrowBindingView for Vec<u8> {
36    type Array = arrow_array::BinaryArray;
37    type View<'a> = &'a [u8];
38
39    fn get_view(
40        array: &Self::Array,
41        index: usize,
42    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
43        if index >= array.len() {
44            return Err(crate::schema::ViewAccessError::OutOfBounds {
45                index,
46                len: array.len(),
47                field_name: None,
48            });
49        }
50        if array.is_null(index) {
51            return Err(crate::schema::ViewAccessError::UnexpectedNull {
52                index,
53                field_name: None,
54            });
55        }
56        Ok(array.value(index))
57    }
58}
59
60// FixedSizeBinary: [u8; N]
61impl<const N: usize> super::ArrowBinding for [u8; N] {
62    type Builder = FixedSizeBinaryBuilder;
63    type Array = FixedSizeBinaryArray;
64    fn data_type() -> DataType {
65        DataType::FixedSizeBinary(i32::try_from(N).expect("width fits i32"))
66    }
67    fn new_builder(capacity: usize) -> Self::Builder {
68        FixedSizeBinaryBuilder::with_capacity(capacity, i32::try_from(N).expect("width fits i32"))
69    }
70    fn append_value(b: &mut Self::Builder, v: &Self) {
71        let _ = b.append_value(v);
72    }
73    fn append_null(b: &mut Self::Builder) {
74        b.append_null();
75    }
76    fn finish(mut b: Self::Builder) -> Self::Array {
77        b.finish()
78    }
79}
80
81#[cfg(feature = "views")]
82impl<const N: usize> super::ArrowBindingView for [u8; N] {
83    type Array = FixedSizeBinaryArray;
84    type View<'a> = &'a [u8];
85
86    fn get_view(
87        array: &Self::Array,
88        index: usize,
89    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
90        if index >= array.len() {
91            return Err(crate::schema::ViewAccessError::OutOfBounds {
92                index,
93                len: array.len(),
94                field_name: None,
95            });
96        }
97        if array.is_null(index) {
98            return Err(crate::schema::ViewAccessError::UnexpectedNull {
99                index,
100                field_name: None,
101            });
102        }
103        Ok(array.value(index))
104    }
105}
106
107/// Wrapper denoting Arrow `LargeBinary` values. Use when individual binary values
108/// can exceed 2GB or when 64-bit offsets are preferred.
109pub struct LargeBinary(Vec<u8>);
110
111impl LargeBinary {
112    /// Construct a new `LargeBinary` from the given bytes.
113    #[inline]
114    #[must_use]
115    pub fn new(value: Vec<u8>) -> Self {
116        Self(value)
117    }
118    /// Return the underlying bytes as a slice.
119    #[inline]
120    #[must_use]
121    pub fn as_slice(&self) -> &[u8] {
122        self.0.as_slice()
123    }
124    /// Consume and return the underlying byte vector.
125    #[inline]
126    #[must_use]
127    pub fn into_vec(self) -> Vec<u8> {
128        self.0
129    }
130}
131
132impl From<Vec<u8>> for LargeBinary {
133    #[inline]
134    fn from(value: Vec<u8>) -> Self {
135        Self::new(value)
136    }
137}
138
139impl ArrowBinding for LargeBinary {
140    type Builder = LargeBinaryBuilder;
141    type Array = LargeBinaryArray;
142    fn data_type() -> DataType {
143        DataType::LargeBinary
144    }
145    fn new_builder(capacity: usize) -> Self::Builder {
146        LargeBinaryBuilder::with_capacity(capacity, 0)
147    }
148    fn append_value(b: &mut Self::Builder, v: &Self) {
149        b.append_value(v.0.as_slice());
150    }
151    fn append_null(b: &mut Self::Builder) {
152        b.append_null();
153    }
154    fn finish(mut b: Self::Builder) -> Self::Array {
155        b.finish()
156    }
157}
158
159#[cfg(feature = "views")]
160impl ArrowBindingView for LargeBinary {
161    type Array = LargeBinaryArray;
162    type View<'a> = &'a [u8];
163
164    fn get_view(
165        array: &Self::Array,
166        index: usize,
167    ) -> Result<Self::View<'_>, crate::schema::ViewAccessError> {
168        if index >= array.len() {
169            return Err(crate::schema::ViewAccessError::OutOfBounds {
170                index,
171                len: array.len(),
172                field_name: None,
173            });
174        }
175        if array.is_null(index) {
176            return Err(crate::schema::ViewAccessError::UnexpectedNull {
177                index,
178                field_name: None,
179            });
180        }
181        Ok(array.value(index))
182    }
183}