typed_arrow/bridge/
binary.rs

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