arrow_array/builder/
fixed_size_binary_builder.rs1use crate::array::Array;
19use crate::builder::ArrayBuilder;
20use crate::{ArrayRef, FixedSizeBinaryArray};
21use arrow_buffer::Buffer;
22use arrow_buffer::NullBufferBuilder;
23use arrow_data::ArrayData;
24use arrow_schema::{ArrowError, DataType};
25use std::any::Any;
26use std::sync::Arc;
27
28#[derive(Debug)]
45pub struct FixedSizeBinaryBuilder {
46 values_builder: Vec<u8>,
47 null_buffer_builder: NullBufferBuilder,
48 value_length: i32,
49}
50
51impl FixedSizeBinaryBuilder {
52 pub fn new(byte_width: i32) -> Self {
54 Self::with_capacity(1024, byte_width)
55 }
56
57 pub fn with_capacity(capacity: usize, byte_width: i32) -> Self {
64 assert!(
65 byte_width >= 0,
66 "value length ({byte_width}) of the array must >= 0"
67 );
68 Self {
69 values_builder: Vec::with_capacity(capacity * byte_width as usize),
70 null_buffer_builder: NullBufferBuilder::new(capacity),
71 value_length: byte_width,
72 }
73 }
74
75 #[inline]
80 pub fn append_value(&mut self, value: impl AsRef<[u8]>) -> Result<(), ArrowError> {
81 if self.value_length != value.as_ref().len() as i32 {
82 Err(ArrowError::InvalidArgumentError(
83 "Byte slice does not have the same length as FixedSizeBinaryBuilder value lengths"
84 .to_string(),
85 ))
86 } else {
87 self.values_builder.extend_from_slice(value.as_ref());
88 self.null_buffer_builder.append_non_null();
89 Ok(())
90 }
91 }
92
93 #[inline]
95 pub fn append_null(&mut self) {
96 self.values_builder
97 .extend(std::iter::repeat_n(0u8, self.value_length as usize));
98 self.null_buffer_builder.append_null();
99 }
100
101 #[inline]
103 pub fn append_nulls(&mut self, n: usize) {
104 self.values_builder
105 .extend(std::iter::repeat_n(0u8, self.value_length as usize * n));
106 self.null_buffer_builder.append_n_nulls(n);
107 }
108
109 pub fn append_array(&mut self, array: &FixedSizeBinaryArray) -> Result<(), ArrowError> {
111 if self.value_length != array.value_length() {
112 return Err(ArrowError::InvalidArgumentError(
113 "Cannot append FixedSizeBinaryArray with different value length".to_string(),
114 ));
115 }
116 let buffer = array.value_data();
117 self.values_builder.extend_from_slice(buffer);
118 if let Some(validity) = array.nulls() {
119 self.null_buffer_builder.append_buffer(validity);
120 } else {
121 self.null_buffer_builder.append_n_non_nulls(array.len());
122 }
123 Ok(())
124 }
125
126 pub fn values_slice(&self) -> &[u8] {
128 self.values_builder.as_slice()
129 }
130
131 pub fn finish(&mut self) -> FixedSizeBinaryArray {
133 let array_length = self.len();
134 let array_data_builder = ArrayData::builder(DataType::FixedSizeBinary(self.value_length))
135 .add_buffer(std::mem::take(&mut self.values_builder).into())
136 .nulls(self.null_buffer_builder.finish())
137 .len(array_length);
138 let array_data = unsafe { array_data_builder.build_unchecked() };
140 FixedSizeBinaryArray::from(array_data)
141 }
142
143 pub fn finish_cloned(&self) -> FixedSizeBinaryArray {
145 let array_length = self.len();
146 let values_buffer = Buffer::from_slice_ref(self.values_builder.as_slice());
147 let array_data_builder = ArrayData::builder(DataType::FixedSizeBinary(self.value_length))
148 .add_buffer(values_buffer)
149 .nulls(self.null_buffer_builder.finish_cloned())
150 .len(array_length);
151 let array_data = unsafe { array_data_builder.build_unchecked() };
153 FixedSizeBinaryArray::from(array_data)
154 }
155
156 pub fn validity_slice(&self) -> Option<&[u8]> {
158 self.null_buffer_builder.as_slice()
159 }
160 pub fn capacity(&self) -> usize {
162 self.values_builder.capacity() + self.null_buffer_builder.allocated_size() + 4 }
164}
165
166impl ArrayBuilder for FixedSizeBinaryBuilder {
167 fn as_any(&self) -> &dyn Any {
169 self
170 }
171
172 fn as_any_mut(&mut self) -> &mut dyn Any {
174 self
175 }
176
177 fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
179 self
180 }
181
182 fn len(&self) -> usize {
184 self.null_buffer_builder.len()
185 }
186
187 fn finish(&mut self) -> ArrayRef {
189 Arc::new(self.finish())
190 }
191
192 fn finish_cloned(&self) -> ArrayRef {
194 Arc::new(self.finish_cloned())
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 use crate::Array;
203
204 #[test]
205 fn test_fixed_size_binary_builder() {
206 let mut builder = FixedSizeBinaryBuilder::with_capacity(3, 5);
207
208 builder.append_value(b"hello").unwrap();
210 builder.append_null();
211 builder.append_value(b"arrow").unwrap();
212 builder.append_nulls(2);
213 builder.append_value(b"world").unwrap();
214 let array = builder.finish();
215
216 assert_eq!(&DataType::FixedSizeBinary(5), array.data_type());
217 assert_eq!(6, array.len());
218 assert_eq!(3, array.null_count());
219 assert_eq!(5, array.value_length());
220 assert_eq!(b"arrow", array.value(2));
221 assert!(array.is_null(3));
222 assert!(array.is_null(4));
223 assert_eq!(b"world", array.value(5));
224 }
225
226 #[test]
227 fn test_fixed_size_binary_builder_finish_cloned() {
228 let mut builder = FixedSizeBinaryBuilder::with_capacity(3, 5);
229
230 builder.append_value(b"hello").unwrap();
232 builder.append_null();
233 builder.append_value(b"arrow").unwrap();
234 let mut array = builder.finish_cloned();
235
236 assert_eq!(&DataType::FixedSizeBinary(5), array.data_type());
237 assert_eq!(3, array.len());
238 assert_eq!(1, array.null_count());
239 assert_eq!(5, array.value_length());
240 assert_eq!(b"arrow", array.value(2));
241
242 builder.append_value(b"finis").unwrap();
244 builder.append_null();
245 builder.append_value(b"clone").unwrap();
246
247 array = builder.finish();
248
249 assert_eq!(&DataType::FixedSizeBinary(5), array.data_type());
250 assert_eq!(6, array.len());
251 assert_eq!(2, array.null_count());
252 assert_eq!(5, array.value_length());
253 assert_eq!(b"clone", array.value(5));
254 }
255
256 #[test]
257 fn test_fixed_size_binary_builder_with_zero_value_length() {
258 let mut builder = FixedSizeBinaryBuilder::new(0);
259
260 builder.append_value(b"").unwrap();
261 builder.append_null();
262 builder.append_value(b"").unwrap();
263 assert!(!builder.is_empty());
264
265 let array = builder.finish();
266 assert_eq!(&DataType::FixedSizeBinary(0), array.data_type());
267 assert_eq!(3, array.len());
268 assert_eq!(1, array.null_count());
269 assert_eq!(0, array.value_length());
270 assert_eq!(b"", array.value(0));
271 assert_eq!(b"", array.value(2));
272 }
273
274 #[test]
275 #[should_panic(
276 expected = "Byte slice does not have the same length as FixedSizeBinaryBuilder value lengths"
277 )]
278 fn test_fixed_size_binary_builder_with_inconsistent_value_length() {
279 let mut builder = FixedSizeBinaryBuilder::with_capacity(1, 4);
280 builder.append_value(b"hello").unwrap();
281 }
282 #[test]
283 fn test_fixed_size_binary_builder_empty() {
284 let mut builder = FixedSizeBinaryBuilder::new(5);
285 assert!(builder.is_empty());
286
287 let fixed_size_binary_array = builder.finish();
288 assert_eq!(
289 &DataType::FixedSizeBinary(5),
290 fixed_size_binary_array.data_type()
291 );
292 assert_eq!(0, fixed_size_binary_array.len());
293 }
294
295 #[test]
296 #[should_panic(expected = "value length (-1) of the array must >= 0")]
297 fn test_fixed_size_binary_builder_invalid_value_length() {
298 let _ = FixedSizeBinaryBuilder::with_capacity(15, -1);
299 }
300
301 #[test]
302 fn test_fixed_size_binary_builder_append_array() {
303 let mut other_builder = FixedSizeBinaryBuilder::with_capacity(3, 5);
304 other_builder.append_value(b"hello").unwrap();
305 other_builder.append_null();
306 other_builder.append_value(b"arrow").unwrap();
307 let other_array = other_builder.finish();
308
309 let mut builder = FixedSizeBinaryBuilder::with_capacity(6, 5);
310 builder.append_array(&other_array).unwrap();
311 builder.append_array(&other_array).unwrap();
313 let array = builder.finish();
314
315 assert_eq!(array.value_length(), other_array.value_length());
316 assert_eq!(&DataType::FixedSizeBinary(5), array.data_type());
317 assert_eq!(6, array.len());
318 assert_eq!(2, array.null_count());
319 assert_eq!(b"hello", array.value(0));
320 assert!(array.is_null(1));
321 assert_eq!(b"arrow", array.value(2));
322
323 assert_eq!(b"hello", array.value(3));
324 assert!(array.is_null(4));
325 assert_eq!(b"arrow", array.value(5));
326 }
327
328 #[test]
329 #[should_panic(expected = "Cannot append FixedSizeBinaryArray with different value length")]
330 fn test_fixed_size_binary_builder_append_array_invalid_value_length() {
331 let mut other_builder = FixedSizeBinaryBuilder::with_capacity(3, 4);
332 other_builder.append_value(b"test").unwrap();
333 let other_array = other_builder.finish();
334 let mut builder = FixedSizeBinaryBuilder::with_capacity(3, 5);
335 builder.append_array(&other_array).unwrap();
336 }
337}