1use std::any::Any;
5use std::mem::MaybeUninit;
6
7use vortex_buffer::BufferAllocatorRef;
8use vortex_buffer::BufferMut;
9use vortex_error::VortexExpect;
10use vortex_error::VortexResult;
11use vortex_error::vortex_ensure;
12use vortex_mask::Mask;
13
14use crate::ArrayRef;
15use crate::ExecutionCtx;
16use crate::IntoArray;
17use crate::arrays::PrimitiveArray;
18use crate::builders::ArrayBuilder;
19use crate::builders::DEFAULT_BUILDER_CAPACITY;
20use crate::builders::LazyBitBufferBuilder;
21use crate::canonical::Canonical;
22use crate::dtype::DType;
23use crate::dtype::NativePType;
24use crate::dtype::Nullability;
25use crate::scalar::Scalar;
26
27pub struct PrimitiveBuilder<T> {
29 dtype: DType,
30 values: BufferMut<T>,
31 nulls: LazyBitBufferBuilder,
32}
33
34impl<T: NativePType> PrimitiveBuilder<T> {
35 #[deprecated(note = "use `new_in` with an explicit allocator")]
37 pub fn new(nullability: Nullability) -> Self {
38 Self::new_in(nullability, BufferAllocatorRef::static_ref())
39 }
40
41 pub fn new_in(nullability: Nullability, allocator: &BufferAllocatorRef) -> Self {
43 Self::with_capacity_in(nullability, DEFAULT_BUILDER_CAPACITY, allocator)
44 }
45
46 #[deprecated(note = "use `with_capacity_in` with an explicit allocator")]
48 pub fn with_capacity(nullability: Nullability, capacity: usize) -> Self {
49 Self::with_capacity_in(nullability, capacity, BufferAllocatorRef::static_ref())
50 }
51
52 pub fn with_capacity_in(
54 nullability: Nullability,
55 capacity: usize,
56 allocator: &BufferAllocatorRef,
57 ) -> Self {
58 Self {
59 values: BufferMut::with_capacity_in(capacity, allocator.clone()),
60 nulls: LazyBitBufferBuilder::new(capacity, allocator.clone()),
61 dtype: DType::Primitive(T::PTYPE, nullability),
62 }
63 }
64
65 pub fn append_value(&mut self, value: T) {
67 self.values.push(value);
68 self.nulls.append_non_null();
69 }
70
71 pub fn append_n_values(&mut self, value: T, n: usize) {
73 self.values.push_n(value, n);
74 self.nulls.append_n_non_nulls(n);
75 }
76
77 pub fn values(&self) -> &[T] {
79 self.values.as_ref()
80 }
81
82 pub fn values_mut(&mut self) -> &mut [T] {
84 self.values.as_mut()
85 }
86
87 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
122 assert_ne!(0, len, "cannot create an uninit range of length 0");
123
124 let current_len = self.values.len();
125 assert!(
126 current_len + len <= self.values.capacity(),
127 "uninit_range of len {len} exceeds builder with length {} and capacity {}",
128 current_len,
129 self.values.capacity()
130 );
131
132 UninitRange { len, builder: self }
133 }
134
135 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
137 let validity = self
138 .nulls
139 .finish_with_nullability(self.dtype().nullability());
140
141 let values = self.values.take().freeze();
142 PrimitiveArray::new(values, validity)
143 }
144
145 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: &Mask) {
147 self.values.extend(iter);
148 self.nulls.append_validity_mask(mask);
149 }
150
151 pub(crate) fn append_primitive_array(
152 &mut self,
153 array: &PrimitiveArray,
154 ctx: &mut ExecutionCtx,
155 ) -> VortexResult<()> {
156 debug_assert_eq!(
157 array.ptype(),
158 T::PTYPE,
159 "Cannot append primitive array with different ptype"
160 );
161
162 self.values.extend_from_slice(array.as_slice::<T>());
163 self.nulls.append_validity_mask(
164 &array
165 .as_ref()
166 .validity()
167 .vortex_expect("validity_mask")
168 .execute_mask(array.as_ref().len(), ctx)?,
169 );
170 Ok(())
171 }
172}
173
174impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
175 fn as_any(&self) -> &dyn Any {
176 self
177 }
178
179 fn as_any_mut(&mut self) -> &mut dyn Any {
180 self
181 }
182
183 fn dtype(&self) -> &DType {
184 &self.dtype
185 }
186
187 fn len(&self) -> usize {
188 self.values.len()
189 }
190
191 fn append_zeros(&mut self, n: usize) {
192 self.values.push_n(T::default(), n);
193 self.nulls.append_n_non_nulls(n);
194 }
195
196 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
197 self.values.push_n(T::default(), n);
198 self.nulls.append_n_nulls(n);
199 }
200
201 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
202 vortex_ensure!(
203 scalar.dtype() == self.dtype(),
204 "PrimitiveBuilder expected scalar with dtype {}, got {}",
205 self.dtype(),
206 scalar.dtype()
207 );
208
209 if let Some(pv) = scalar.as_primitive().pvalue() {
210 self.append_value(pv.cast::<T>()?)
211 } else {
212 self.append_null()
213 }
214
215 Ok(())
216 }
217
218 fn reserve_exact(&mut self, additional: usize) {
219 self.values.reserve(additional);
220 self.nulls.reserve_exact(additional);
221 }
222
223 fn finish(&mut self) -> ArrayRef {
224 self.finish_into_primitive().into_array()
225 }
226
227 fn finish_into_canonical(&mut self, _ctx: &mut ExecutionCtx) -> Canonical {
228 Canonical::Primitive(self.finish_into_primitive())
229 }
230}
231
232pub struct UninitRange<'a, T> {
234 len: usize,
238
239 builder: &'a mut PrimitiveBuilder<T>,
244}
245
246impl<T> UninitRange<'_, T> {
247 #[inline]
249 pub fn len(&self) -> usize {
250 self.len
251 }
252
253 #[inline]
255 pub fn is_empty(&self) -> bool {
256 self.len == 0
257 }
258
259 #[inline]
265 pub fn set_value(&mut self, index: usize, value: T) {
266 assert!(index < self.len, "index out of bounds");
267 let spare = self.builder.values.spare_capacity_mut();
268 spare[index] = MaybeUninit::new(value);
269 }
270
271 pub unsafe fn append_mask(&mut self, mask: &Mask) {
283 assert_eq!(
284 mask.len(),
285 self.len,
286 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
287 );
288
289 self.builder.nulls.append_validity_mask(mask);
294 }
295
296 pub fn set_validity_bit(&mut self, index: usize, v: bool) {
303 assert!(index < self.len, "set_bit index out of bounds");
304 let absolute_index = self.builder.values.len() + index;
307 self.builder.nulls.set_bit(absolute_index, v);
308 }
309
310 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
315 where
316 T: Copy,
317 {
318 debug_assert!(
319 local_offset + src.len() <= self.len,
320 "tried to copy a slice into a `UninitRange` past its boundary"
321 );
322
323 let dst =
326 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
327 dst.write_copy_of_slice(src);
328 }
329
330 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
344 assert!(
345 offset + len <= self.len,
346 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
347 offset,
348 len,
349 self.len
350 );
351 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
352 }
353
354 pub unsafe fn finish(self) {
368 let new_len = self.builder.values.len() + self.len;
370 unsafe { self.builder.values.set_len(new_len) };
371 }
372}
373
374#[cfg(test)]
375mod tests {
376 use vortex_error::VortexExpect;
377
378 use super::*;
379 use crate::VortexSessionExecute;
380 use crate::array_session;
381 use crate::assert_arrays_eq;
382
383 #[test]
388 fn test_multiple_uninit_ranges_correct_offsets() {
389 let mut ctx = array_session().create_execution_ctx();
390 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
391 Nullability::NonNullable,
392 10,
393 BufferAllocatorRef::static_ref(),
394 );
395
396 let mut range1 = builder.uninit_range(3);
398 range1.copy_from_slice(0, &[1, 2, 3]);
399
400 unsafe {
402 range1.finish();
403 }
404
405 assert_eq!(builder.values(), &[1, 2, 3]);
407
408 let mut range2 = builder.uninit_range(2);
410
411 range2.copy_from_slice(0, &[4, 5]);
413
414 unsafe {
416 range2.finish();
417 }
418
419 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
421
422 let array = builder.finish_into_primitive();
423 assert_arrays_eq!(
424 array,
425 PrimitiveArray::from_iter([1i32, 2, 3, 4, 5]),
426 &mut ctx
427 );
428 }
429
430 #[test]
436 fn test_append_mask_on_uninit_range() {
437 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
438 Nullability::Nullable,
439 5,
440 BufferAllocatorRef::static_ref(),
441 );
442 let mut range = builder.uninit_range(3);
443
444 let mask = Mask::from_iter([true, false, true]);
446
447 unsafe {
449 range.append_mask(&mask);
450 }
451
452 range.copy_from_slice(0, &[10, 20, 30]);
454
455 unsafe {
457 range.finish();
458 }
459
460 let array = builder.finish_into_primitive();
461 assert_eq!(array.len(), 3);
462 assert!(
464 !array
465 .execute_scalar(0, &mut array_session().create_execution_ctx())
466 .unwrap()
467 .is_null()
468 );
469 assert!(
470 array
471 .execute_scalar(1, &mut array_session().create_execution_ctx())
472 .unwrap()
473 .is_null()
474 );
475 assert!(
476 !array
477 .execute_scalar(2, &mut array_session().create_execution_ctx())
478 .unwrap()
479 .is_null()
480 );
481 }
482
483 #[test]
487 #[should_panic(
488 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
489 )]
490 fn test_append_mask_wrong_length_panics() {
491 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
492 Nullability::Nullable,
493 10,
494 BufferAllocatorRef::static_ref(),
495 );
496 let mut range = builder.uninit_range(5);
497
498 let wrong_mask = Mask::from_iter([true, false, true]);
500
501 unsafe {
503 range.append_mask(&wrong_mask);
504 }
505 }
506
507 #[test]
511 fn test_copy_from_slice_with_offsets() {
512 let mut ctx = array_session().create_execution_ctx();
513 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
514 Nullability::NonNullable,
515 10,
516 BufferAllocatorRef::static_ref(),
517 );
518 let mut range = builder.uninit_range(6);
519
520 range.copy_from_slice(0, &[1, 2]);
522 range.copy_from_slice(2, &[3, 4]);
523 range.copy_from_slice(4, &[5, 6]);
524
525 unsafe {
527 range.finish();
528 }
529
530 let array = builder.finish_into_primitive();
531 assert_arrays_eq!(
532 array,
533 PrimitiveArray::from_iter([1i32, 2, 3, 4, 5, 6]),
534 &mut ctx
535 );
536 }
537
538 #[test]
544 fn test_set_bit_relative_indexing() {
545 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
546 Nullability::Nullable,
547 10,
548 BufferAllocatorRef::static_ref(),
549 );
550
551 builder.append_value(100);
553 builder.append_value(200);
554
555 let mut range = builder.uninit_range(3);
557
558 let initial_mask = Mask::from_iter([false, false, false]);
560 unsafe {
562 range.append_mask(&initial_mask);
563 }
564
565 range.set_validity_bit(0, true); range.set_validity_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
572
573 unsafe {
575 range.finish();
576 }
577
578 let array = builder.finish_into_primitive();
579
580 assert_eq!(array.len(), 5);
582 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
583
584 assert!(
586 !array
587 .execute_scalar(0, &mut array_session().create_execution_ctx())
588 .unwrap()
589 .is_null()
590 ); assert!(
592 !array
593 .execute_scalar(1, &mut array_session().create_execution_ctx())
594 .unwrap()
595 .is_null()
596 ); assert!(
600 !array
601 .execute_scalar(2, &mut array_session().create_execution_ctx())
602 .unwrap()
603 .is_null()
604 ); assert!(
606 array
607 .execute_scalar(3, &mut array_session().create_execution_ctx())
608 .unwrap()
609 .is_null()
610 ); assert!(
612 !array
613 .execute_scalar(4, &mut array_session().create_execution_ctx())
614 .unwrap()
615 .is_null()
616 ); }
618
619 #[test]
621 #[should_panic(expected = "cannot create an uninit range of length 0")]
622 fn test_zero_length_uninit_range_panics() {
623 let mut builder = PrimitiveBuilder::<i32>::new_in(
624 Nullability::NonNullable,
625 BufferAllocatorRef::static_ref(),
626 );
627 let _range = builder.uninit_range(0);
628 }
629
630 #[test]
632 #[should_panic(expected = "uninit_range of len 261 exceeds builder with length 0 and capacity")]
633 fn test_uninit_range_exceeds_capacity_panics() {
634 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
635 Nullability::NonNullable,
636 5,
637 BufferAllocatorRef::static_ref(),
638 );
639 let _range = builder.uninit_range(261);
640 }
641
642 #[test]
646 #[cfg(debug_assertions)]
647 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
648 fn test_copy_from_slice_out_of_bounds() {
649 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
650 Nullability::NonNullable,
651 10,
652 BufferAllocatorRef::static_ref(),
653 );
654 let mut range = builder.uninit_range(3);
655
656 range.copy_from_slice(1, &[1, 2, 3]);
658 }
659
660 #[test]
664 fn test_finish_unsafe_contract() {
665 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
666 Nullability::Nullable,
667 5,
668 BufferAllocatorRef::static_ref(),
669 );
670 let mut range = builder.uninit_range(3);
671
672 let mask = Mask::from_iter([true, true, false]);
674 unsafe {
676 range.append_mask(&mask);
677 }
678
679 range.copy_from_slice(0, &[10, 20, 30]);
681
682 unsafe {
684 range.finish();
685 }
686
687 let array = builder.finish_into_primitive();
688 assert_eq!(array.len(), 3);
689 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
690 }
691
692 #[test]
693 fn test_append_scalar() {
694 use crate::dtype::DType;
695 use crate::scalar::Scalar;
696
697 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
698 Nullability::Nullable,
699 10,
700 BufferAllocatorRef::static_ref(),
701 );
702
703 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
705 builder.append_scalar(&scalar1).unwrap();
706
707 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
709 builder.append_scalar(&scalar2).unwrap();
710
711 let null_scalar = Scalar::null(DType::Primitive(
713 crate::dtype::PType::I32,
714 Nullability::Nullable,
715 ));
716 builder.append_scalar(&null_scalar).unwrap();
717
718 let array = builder.finish_into_primitive();
719 assert_eq!(array.len(), 3);
720
721 let values = array.as_slice::<i32>();
723 assert_eq!(values[0], 42);
724 assert_eq!(values[1], 84);
725 let mut ctx = array_session().create_execution_ctx();
729 assert!(
730 array
731 .validity()
732 .vortex_expect("primitive validity should be derivable")
733 .execute_is_valid(0, &mut ctx)
734 .unwrap()
735 );
736 assert!(
737 array
738 .validity()
739 .vortex_expect("primitive validity should be derivable")
740 .execute_is_valid(1, &mut ctx)
741 .unwrap()
742 );
743 assert!(
744 !array
745 .validity()
746 .vortex_expect("primitive validity should be derivable")
747 .execute_is_valid(2, &mut ctx)
748 .unwrap()
749 );
750
751 let mut builder = PrimitiveBuilder::<i32>::with_capacity_in(
753 Nullability::NonNullable,
754 10,
755 BufferAllocatorRef::static_ref(),
756 );
757 let wrong_scalar = Scalar::from(true);
758 assert!(builder.append_scalar(&wrong_scalar).is_err());
759 }
760}