polars_arrow/array/fixed_size_binary/
mod.rs1use super::{Array, Splitable};
2use crate::bitmap::Bitmap;
3use crate::buffer::Buffer;
4use crate::datatypes::ArrowDataType;
5
6mod builder;
7mod ffi;
8pub(super) mod fmt;
9mod iterator;
10pub use builder::*;
11mod mutable;
12pub use mutable::*;
13use polars_error::{PolarsResult, polars_bail, polars_ensure};
14
15#[derive(Clone)]
18pub struct FixedSizeBinaryArray {
19 size: usize, dtype: ArrowDataType,
21 values: Buffer<u8>,
22 validity: Option<Bitmap>,
23}
24
25impl FixedSizeBinaryArray {
26 pub fn try_new(
34 dtype: ArrowDataType,
35 values: Buffer<u8>,
36 validity: Option<Bitmap>,
37 ) -> PolarsResult<Self> {
38 let size = Self::maybe_get_size(&dtype)?;
39
40 if values.len() % size != 0 {
41 polars_bail!(ComputeError:
42 "values (of len {}) must be a multiple of size ({}) in FixedSizeBinaryArray.",
43 values.len(),
44 size
45 )
46 }
47 let len = values.len() / size;
48
49 if validity
50 .as_ref()
51 .is_some_and(|validity| validity.len() != len)
52 {
53 polars_bail!(ComputeError: "validity mask length must be equal to the number of values divided by size")
54 }
55
56 Ok(Self {
57 size,
58 dtype,
59 values,
60 validity,
61 })
62 }
63
64 pub fn new(dtype: ArrowDataType, values: Buffer<u8>, validity: Option<Bitmap>) -> Self {
71 Self::try_new(dtype, values, validity).unwrap()
72 }
73
74 pub fn new_empty(dtype: ArrowDataType) -> Self {
76 Self::new(dtype, Buffer::new(), None)
77 }
78
79 pub fn new_null(dtype: ArrowDataType, length: usize) -> Self {
81 let size = Self::maybe_get_size(&dtype).unwrap();
82 Self::new(
83 dtype,
84 vec![0u8; length * size].into(),
85 Some(Bitmap::new_zeroed(length)),
86 )
87 }
88}
89
90impl FixedSizeBinaryArray {
92 pub fn slice(&mut self, offset: usize, length: usize) {
98 assert!(
99 offset + length <= self.len(),
100 "the offset of the new Buffer cannot exceed the existing length"
101 );
102 unsafe { self.slice_unchecked(offset, length) }
103 }
104
105 pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
112 self.validity = self
113 .validity
114 .take()
115 .map(|bitmap| bitmap.sliced_unchecked(offset, length))
116 .filter(|bitmap| bitmap.unset_bits() > 0);
117 self.values
118 .slice_unchecked(offset * self.size, length * self.size);
119 }
120
121 impl_sliced!();
122 impl_mut_validity!();
123 impl_into_array!();
124}
125
126impl FixedSizeBinaryArray {
128 #[inline]
130 pub fn len(&self) -> usize {
131 self.values.len() / self.size
132 }
133
134 #[inline]
136 pub fn validity(&self) -> Option<&Bitmap> {
137 self.validity.as_ref()
138 }
139
140 pub fn values(&self) -> &Buffer<u8> {
142 &self.values
143 }
144
145 #[inline]
149 pub fn value(&self, i: usize) -> &[u8] {
150 assert!(i < self.len());
151 unsafe { self.value_unchecked(i) }
152 }
153
154 #[inline]
159 pub unsafe fn value_unchecked(&self, i: usize) -> &[u8] {
160 self.values
162 .get_unchecked(i * self.size..(i + 1) * self.size)
163 }
164
165 #[inline]
169 pub fn get(&self, i: usize) -> Option<&[u8]> {
170 if !self.is_null(i) {
171 unsafe { Some(self.value_unchecked(i)) }
173 } else {
174 None
175 }
176 }
177
178 #[inline]
183 pub fn to(self, dtype: ArrowDataType) -> Self {
184 match (dtype.to_logical_type(), self.dtype().to_logical_type()) {
185 (ArrowDataType::FixedSizeBinary(size_a), ArrowDataType::FixedSizeBinary(size_b))
186 if size_a == size_b => {},
187 _ => panic!("Wrong DataType"),
188 }
189
190 Self {
191 size: self.size,
192 dtype,
193 values: self.values,
194 validity: self.validity,
195 }
196 }
197
198 pub fn size(&self) -> usize {
200 self.size
201 }
202}
203
204impl FixedSizeBinaryArray {
205 pub(crate) fn maybe_get_size(dtype: &ArrowDataType) -> PolarsResult<usize> {
206 match dtype.to_logical_type() {
207 ArrowDataType::FixedSizeBinary(size) => {
208 polars_ensure!(*size != 0, ComputeError: "FixedSizeBinaryArray expects a positive size");
209 Ok(*size)
210 },
211 other => {
212 polars_bail!(ComputeError: "FixedSizeBinaryArray expects DataType::FixedSizeBinary. found {other:?}")
213 },
214 }
215 }
216
217 pub fn get_size(dtype: &ArrowDataType) -> usize {
218 Self::maybe_get_size(dtype).unwrap()
219 }
220}
221
222impl Array for FixedSizeBinaryArray {
223 impl_common_array!();
224
225 fn validity(&self) -> Option<&Bitmap> {
226 self.validity.as_ref()
227 }
228
229 #[inline]
230 fn with_validity(&self, validity: Option<Bitmap>) -> Box<dyn Array> {
231 Box::new(self.clone().with_validity(validity))
232 }
233}
234
235impl Splitable for FixedSizeBinaryArray {
236 fn check_bound(&self, offset: usize) -> bool {
237 offset < self.len()
238 }
239
240 unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
241 let (lhs_values, rhs_values) = unsafe { self.values.split_at_unchecked(offset) };
242 let (lhs_validity, rhs_validity) = unsafe { self.validity.split_at_unchecked(offset) };
243
244 let size = self.size;
245
246 (
247 Self {
248 dtype: self.dtype.clone(),
249 values: lhs_values,
250 validity: lhs_validity,
251 size,
252 },
253 Self {
254 dtype: self.dtype.clone(),
255 values: rhs_values,
256 validity: rhs_validity,
257 size,
258 },
259 )
260 }
261}
262
263impl FixedSizeBinaryArray {
264 pub fn try_from_iter<P: AsRef<[u8]>, I: IntoIterator<Item = Option<P>>>(
266 iter: I,
267 size: usize,
268 ) -> PolarsResult<Self> {
269 MutableFixedSizeBinaryArray::try_from_iter(iter, size).map(|x| x.into())
270 }
271
272 pub fn from_iter<P: AsRef<[u8]>, I: IntoIterator<Item = Option<P>>>(
274 iter: I,
275 size: usize,
276 ) -> Self {
277 MutableFixedSizeBinaryArray::try_from_iter(iter, size)
278 .unwrap()
279 .into()
280 }
281
282 pub fn from_slice<const N: usize, P: AsRef<[[u8; N]]>>(a: P) -> Self {
284 let values = a.as_ref().iter().flatten().copied().collect::<Vec<_>>();
285 Self::new(ArrowDataType::FixedSizeBinary(N), values.into(), None)
286 }
287
288 pub fn from<const N: usize, P: AsRef<[Option<[u8; N]>]>>(slice: P) -> Self {
291 MutableFixedSizeBinaryArray::from(slice).into()
292 }
293}