1use std::any::Any;
5use std::mem::MaybeUninit;
6
7use vortex_buffer::BufferMut;
8use vortex_error::VortexExpect;
9use vortex_error::VortexResult;
10use vortex_error::vortex_ensure;
11use vortex_mask::Mask;
12
13use crate::ArrayRef;
14use crate::IntoArray;
15use crate::arrays::PrimitiveArray;
16use crate::builders::ArrayBuilder;
17use crate::builders::DEFAULT_BUILDER_CAPACITY;
18use crate::builders::LazyBitBufferBuilder;
19use crate::canonical::Canonical;
20use crate::canonical::ToCanonical;
21use crate::dtype::DType;
22use crate::dtype::NativePType;
23use crate::dtype::Nullability;
24use crate::scalar::Scalar;
25
26pub struct PrimitiveBuilder<T> {
28 dtype: DType,
29 values: BufferMut<T>,
30 nulls: LazyBitBufferBuilder,
31}
32
33impl<T: NativePType> PrimitiveBuilder<T> {
34 pub fn new(nullability: Nullability) -> Self {
36 Self::with_capacity(nullability, DEFAULT_BUILDER_CAPACITY)
37 }
38
39 pub fn with_capacity(nullability: Nullability, capacity: usize) -> Self {
41 Self {
42 values: BufferMut::with_capacity(capacity),
43 nulls: LazyBitBufferBuilder::new(capacity),
44 dtype: DType::Primitive(T::PTYPE, nullability),
45 }
46 }
47
48 pub fn append_value(&mut self, value: T) {
50 self.values.push(value);
51 self.nulls.append_non_null();
52 }
53
54 pub fn append_n_values(&mut self, value: T, n: usize) {
56 self.values.push_n(value, n);
57 self.nulls.append_n_non_nulls(n);
58 }
59
60 pub fn values(&self) -> &[T] {
62 self.values.as_ref()
63 }
64
65 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
99 assert_ne!(0, len, "cannot create an uninit range of length 0");
100
101 let current_len = self.values.len();
102 assert!(
103 current_len + len <= self.values.capacity(),
104 "uninit_range of len {len} exceeds builder with length {} and capacity {}",
105 current_len,
106 self.values.capacity()
107 );
108
109 UninitRange { len, builder: self }
110 }
111
112 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
114 let validity = self
115 .nulls
116 .finish_with_nullability(self.dtype().nullability());
117
118 PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
119 }
120
121 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: Mask) {
123 self.values.extend(iter);
124 self.nulls.append_validity_mask(mask);
125 }
126}
127
128impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
129 fn as_any(&self) -> &dyn Any {
130 self
131 }
132
133 fn as_any_mut(&mut self) -> &mut dyn Any {
134 self
135 }
136
137 fn dtype(&self) -> &DType {
138 &self.dtype
139 }
140
141 fn len(&self) -> usize {
142 self.values.len()
143 }
144
145 fn append_zeros(&mut self, n: usize) {
146 self.values.push_n(T::default(), n);
147 self.nulls.append_n_non_nulls(n);
148 }
149
150 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
151 self.values.push_n(T::default(), n);
152 self.nulls.append_n_nulls(n);
153 }
154
155 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
156 vortex_ensure!(
157 scalar.dtype() == self.dtype(),
158 "PrimitiveBuilder expected scalar with dtype {}, got {}",
159 self.dtype(),
160 scalar.dtype()
161 );
162
163 if let Some(pv) = scalar.as_primitive().pvalue() {
164 self.append_value(pv.cast::<T>()?)
165 } else {
166 self.append_null()
167 }
168
169 Ok(())
170 }
171
172 unsafe fn extend_from_array_unchecked(&mut self, array: &ArrayRef) {
173 let array = array.to_primitive();
174
175 debug_assert_eq!(
177 array.ptype(),
178 T::PTYPE,
179 "Cannot extend from array with different ptype"
180 );
181
182 self.values.extend_from_slice(array.as_slice::<T>());
183 self.nulls.append_validity_mask(
184 array
185 .validity_mask()
186 .vortex_expect("validity_mask in extend_from_array_unchecked"),
187 );
188 }
189
190 fn reserve_exact(&mut self, additional: usize) {
191 self.values.reserve(additional);
192 self.nulls.reserve_exact(additional);
193 }
194
195 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
196 self.nulls = LazyBitBufferBuilder::new(validity.len());
197 self.nulls.append_validity_mask(validity);
198 }
199
200 fn finish(&mut self) -> ArrayRef {
201 self.finish_into_primitive().into_array()
202 }
203
204 fn finish_into_canonical(&mut self) -> Canonical {
205 Canonical::Primitive(self.finish_into_primitive())
206 }
207}
208
209pub struct UninitRange<'a, T> {
211 len: usize,
215
216 builder: &'a mut PrimitiveBuilder<T>,
221}
222
223impl<T> UninitRange<'_, T> {
224 #[inline]
226 pub fn len(&self) -> usize {
227 self.len
228 }
229
230 #[inline]
232 pub fn is_empty(&self) -> bool {
233 self.len == 0
234 }
235
236 #[inline]
242 pub fn set_value(&mut self, index: usize, value: T) {
243 assert!(index < self.len, "index out of bounds");
244 let spare = self.builder.values.spare_capacity_mut();
245 spare[index] = MaybeUninit::new(value);
246 }
247
248 pub unsafe fn append_mask(&mut self, mask: Mask) {
260 assert_eq!(
261 mask.len(),
262 self.len,
263 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
264 );
265
266 self.builder.nulls.append_validity_mask(mask);
271 }
272
273 pub fn set_validity_bit(&mut self, index: usize, v: bool) {
280 assert!(index < self.len, "set_bit index out of bounds");
281 let absolute_index = self.builder.values.len() + index;
284 self.builder.nulls.set_bit(absolute_index, v);
285 }
286
287 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
292 where
293 T: Copy,
294 {
295 debug_assert!(
296 local_offset + src.len() <= self.len,
297 "tried to copy a slice into a `UninitRange` past its boundary"
298 );
299
300 let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
302
303 let dst =
306 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
307 dst.copy_from_slice(uninit_src);
308 }
309
310 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
324 assert!(
325 offset + len <= self.len,
326 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
327 offset,
328 len,
329 self.len
330 );
331 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
332 }
333
334 pub unsafe fn finish(self) {
348 let new_len = self.builder.values.len() + self.len;
350 unsafe { self.builder.values.set_len(new_len) };
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357 use crate::assert_arrays_eq;
358
359 #[test]
364 fn test_multiple_uninit_ranges_correct_offsets() {
365 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
366
367 let mut range1 = builder.uninit_range(3);
369 range1.copy_from_slice(0, &[1, 2, 3]);
370
371 unsafe {
373 range1.finish();
374 }
375
376 assert_eq!(builder.values(), &[1, 2, 3]);
378
379 let mut range2 = builder.uninit_range(2);
381
382 range2.copy_from_slice(0, &[4, 5]);
384
385 unsafe {
387 range2.finish();
388 }
389
390 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
392
393 let array = builder.finish_into_primitive();
394 assert_arrays_eq!(array, PrimitiveArray::from_iter([1i32, 2, 3, 4, 5]));
395 }
396
397 #[test]
403 fn test_append_mask_on_uninit_range() {
404 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
405 let mut range = builder.uninit_range(3);
406
407 let mask = Mask::from_iter([true, false, true]);
409
410 unsafe {
412 range.append_mask(mask);
413 }
414
415 range.copy_from_slice(0, &[10, 20, 30]);
417
418 unsafe {
420 range.finish();
421 }
422
423 let array = builder.finish_into_primitive();
424 assert_eq!(array.len(), 3);
425 assert!(!array.scalar_at(0).unwrap().is_null());
427 assert!(array.scalar_at(1).unwrap().is_null());
428 assert!(!array.scalar_at(2).unwrap().is_null());
429 }
430
431 #[test]
435 #[should_panic(
436 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
437 )]
438 fn test_append_mask_wrong_length_panics() {
439 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
440 let mut range = builder.uninit_range(5);
441
442 let wrong_mask = Mask::from_iter([true, false, true]);
444
445 unsafe {
447 range.append_mask(wrong_mask);
448 }
449 }
450
451 #[test]
455 fn test_copy_from_slice_with_offsets() {
456 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
457 let mut range = builder.uninit_range(6);
458
459 range.copy_from_slice(0, &[1, 2]);
461 range.copy_from_slice(2, &[3, 4]);
462 range.copy_from_slice(4, &[5, 6]);
463
464 unsafe {
466 range.finish();
467 }
468
469 let array = builder.finish_into_primitive();
470 assert_arrays_eq!(array, PrimitiveArray::from_iter([1i32, 2, 3, 4, 5, 6]));
471 }
472
473 #[test]
479 fn test_set_bit_relative_indexing() {
480 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
481
482 builder.append_value(100);
484 builder.append_value(200);
485
486 let mut range = builder.uninit_range(3);
488
489 let initial_mask = Mask::from_iter([false, false, false]);
491 unsafe {
493 range.append_mask(initial_mask);
494 }
495
496 range.set_validity_bit(0, true); range.set_validity_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
503
504 unsafe {
506 range.finish();
507 }
508
509 let array = builder.finish_into_primitive();
510
511 assert_eq!(array.len(), 5);
513 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
514
515 assert!(!array.scalar_at(0).unwrap().is_null()); assert!(!array.scalar_at(1).unwrap().is_null()); assert!(!array.scalar_at(2).unwrap().is_null()); assert!(array.scalar_at(3).unwrap().is_null()); assert!(!array.scalar_at(4).unwrap().is_null()); }
524
525 #[test]
527 #[should_panic(expected = "cannot create an uninit range of length 0")]
528 fn test_zero_length_uninit_range_panics() {
529 let mut builder = PrimitiveBuilder::<i32>::new(Nullability::NonNullable);
530 let _range = builder.uninit_range(0);
531 }
532
533 #[test]
535 #[should_panic(
536 expected = "uninit_range of len 10 exceeds builder with length 0 and capacity 6"
537 )]
538 fn test_uninit_range_exceeds_capacity_panics() {
539 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 5);
540 let _range = builder.uninit_range(10);
541 }
542
543 #[test]
547 #[cfg(debug_assertions)]
548 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
549 fn test_copy_from_slice_out_of_bounds() {
550 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
551 let mut range = builder.uninit_range(3);
552
553 range.copy_from_slice(1, &[1, 2, 3]);
555 }
556
557 #[test]
561 fn test_finish_unsafe_contract() {
562 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
563 let mut range = builder.uninit_range(3);
564
565 let mask = Mask::from_iter([true, true, false]);
567 unsafe {
569 range.append_mask(mask);
570 }
571
572 range.copy_from_slice(0, &[10, 20, 30]);
574
575 unsafe {
577 range.finish();
578 }
579
580 let array = builder.finish_into_primitive();
581 assert_eq!(array.len(), 3);
582 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
583 }
584
585 #[test]
586 fn test_append_scalar() {
587 use crate::dtype::DType;
588 use crate::scalar::Scalar;
589
590 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
591
592 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
594 builder.append_scalar(&scalar1).unwrap();
595
596 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
598 builder.append_scalar(&scalar2).unwrap();
599
600 let null_scalar = Scalar::null(DType::Primitive(
602 crate::dtype::PType::I32,
603 Nullability::Nullable,
604 ));
605 builder.append_scalar(&null_scalar).unwrap();
606
607 let array = builder.finish_into_primitive();
608 assert_eq!(array.len(), 3);
609
610 let values = array.as_slice::<i32>();
612 assert_eq!(values[0], 42);
613 assert_eq!(values[1], 84);
614 use crate::vtable::ValidityHelper;
618 assert!(array.validity().is_valid(0).unwrap());
619 assert!(array.validity().is_valid(1).unwrap());
620 assert!(!array.validity().is_valid(2).unwrap());
621
622 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
624 let wrong_scalar = Scalar::from(true);
625 assert!(builder.append_scalar(&wrong_scalar).is_err());
626 }
627}