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::ExecutionCtx;
15use crate::IntoArray;
16use crate::arrays::PrimitiveArray;
17use crate::builders::ArrayBuilder;
18use crate::builders::DEFAULT_BUILDER_CAPACITY;
19use crate::builders::LazyBitBufferBuilder;
20use crate::canonical::Canonical;
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 values_mut(&mut self) -> &mut [T] {
67 self.values.as_mut()
68 }
69
70 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
104 assert_ne!(0, len, "cannot create an uninit range of length 0");
105
106 let current_len = self.values.len();
107 assert!(
108 current_len + len <= self.values.capacity(),
109 "uninit_range of len {len} exceeds builder with length {} and capacity {}",
110 current_len,
111 self.values.capacity()
112 );
113
114 UninitRange { len, builder: self }
115 }
116
117 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
119 let validity = self
120 .nulls
121 .finish_with_nullability(self.dtype().nullability());
122
123 PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
124 }
125
126 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: &Mask) {
128 self.values.extend(iter);
129 self.nulls.append_validity_mask(mask);
130 }
131
132 pub(crate) fn append_primitive_array(
133 &mut self,
134 array: &PrimitiveArray,
135 ctx: &mut ExecutionCtx,
136 ) -> VortexResult<()> {
137 debug_assert_eq!(
138 array.ptype(),
139 T::PTYPE,
140 "Cannot append primitive array with different ptype"
141 );
142
143 self.values.extend_from_slice(array.as_slice::<T>());
144 self.nulls.append_validity_mask(
145 &array
146 .as_ref()
147 .validity()
148 .vortex_expect("validity_mask")
149 .execute_mask(array.as_ref().len(), ctx)?,
150 );
151 Ok(())
152 }
153}
154
155impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
156 fn as_any(&self) -> &dyn Any {
157 self
158 }
159
160 fn as_any_mut(&mut self) -> &mut dyn Any {
161 self
162 }
163
164 fn dtype(&self) -> &DType {
165 &self.dtype
166 }
167
168 fn len(&self) -> usize {
169 self.values.len()
170 }
171
172 fn append_zeros(&mut self, n: usize) {
173 self.values.push_n(T::default(), n);
174 self.nulls.append_n_non_nulls(n);
175 }
176
177 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
178 self.values.push_n(T::default(), n);
179 self.nulls.append_n_nulls(n);
180 }
181
182 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
183 vortex_ensure!(
184 scalar.dtype() == self.dtype(),
185 "PrimitiveBuilder expected scalar with dtype {}, got {}",
186 self.dtype(),
187 scalar.dtype()
188 );
189
190 if let Some(pv) = scalar.as_primitive().pvalue() {
191 self.append_value(pv.cast::<T>()?)
192 } else {
193 self.append_null()
194 }
195
196 Ok(())
197 }
198
199 fn reserve_exact(&mut self, additional: usize) {
200 self.values.reserve(additional);
201 self.nulls.reserve_exact(additional);
202 }
203
204 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
205 self.nulls = LazyBitBufferBuilder::from_validity_mask(validity);
206 }
207
208 fn finish(&mut self) -> ArrayRef {
209 self.finish_into_primitive().into_array()
210 }
211
212 fn finish_into_canonical(&mut self, _ctx: &mut ExecutionCtx) -> Canonical {
213 Canonical::Primitive(self.finish_into_primitive())
214 }
215}
216
217pub struct UninitRange<'a, T> {
219 len: usize,
223
224 builder: &'a mut PrimitiveBuilder<T>,
229}
230
231impl<T> UninitRange<'_, T> {
232 #[inline]
234 pub fn len(&self) -> usize {
235 self.len
236 }
237
238 #[inline]
240 pub fn is_empty(&self) -> bool {
241 self.len == 0
242 }
243
244 #[inline]
250 pub fn set_value(&mut self, index: usize, value: T) {
251 assert!(index < self.len, "index out of bounds");
252 let spare = self.builder.values.spare_capacity_mut();
253 spare[index] = MaybeUninit::new(value);
254 }
255
256 pub unsafe fn append_mask(&mut self, mask: &Mask) {
268 assert_eq!(
269 mask.len(),
270 self.len,
271 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
272 );
273
274 self.builder.nulls.append_validity_mask(mask);
279 }
280
281 pub fn set_validity_bit(&mut self, index: usize, v: bool) {
288 assert!(index < self.len, "set_bit index out of bounds");
289 let absolute_index = self.builder.values.len() + index;
292 self.builder.nulls.set_bit(absolute_index, v);
293 }
294
295 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
300 where
301 T: Copy,
302 {
303 debug_assert!(
304 local_offset + src.len() <= self.len,
305 "tried to copy a slice into a `UninitRange` past its boundary"
306 );
307
308 let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
310
311 let dst =
314 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
315 dst.copy_from_slice(uninit_src);
316 }
317
318 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
332 assert!(
333 offset + len <= self.len,
334 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
335 offset,
336 len,
337 self.len
338 );
339 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
340 }
341
342 pub unsafe fn finish(self) {
356 let new_len = self.builder.values.len() + self.len;
358 unsafe { self.builder.values.set_len(new_len) };
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use vortex_error::VortexExpect;
365
366 use super::*;
367 use crate::VortexSessionExecute;
368 use crate::array_session;
369 use crate::assert_arrays_eq;
370
371 #[test]
376 fn test_multiple_uninit_ranges_correct_offsets() {
377 let mut ctx = array_session().create_execution_ctx();
378 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
379
380 let mut range1 = builder.uninit_range(3);
382 range1.copy_from_slice(0, &[1, 2, 3]);
383
384 unsafe {
386 range1.finish();
387 }
388
389 assert_eq!(builder.values(), &[1, 2, 3]);
391
392 let mut range2 = builder.uninit_range(2);
394
395 range2.copy_from_slice(0, &[4, 5]);
397
398 unsafe {
400 range2.finish();
401 }
402
403 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
405
406 let array = builder.finish_into_primitive();
407 assert_arrays_eq!(
408 array,
409 PrimitiveArray::from_iter([1i32, 2, 3, 4, 5]),
410 &mut ctx
411 );
412 }
413
414 #[test]
420 fn test_append_mask_on_uninit_range() {
421 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
422 let mut range = builder.uninit_range(3);
423
424 let mask = Mask::from_iter([true, false, true]);
426
427 unsafe {
429 range.append_mask(&mask);
430 }
431
432 range.copy_from_slice(0, &[10, 20, 30]);
434
435 unsafe {
437 range.finish();
438 }
439
440 let array = builder.finish_into_primitive();
441 assert_eq!(array.len(), 3);
442 assert!(
444 !array
445 .execute_scalar(0, &mut array_session().create_execution_ctx())
446 .unwrap()
447 .is_null()
448 );
449 assert!(
450 array
451 .execute_scalar(1, &mut array_session().create_execution_ctx())
452 .unwrap()
453 .is_null()
454 );
455 assert!(
456 !array
457 .execute_scalar(2, &mut array_session().create_execution_ctx())
458 .unwrap()
459 .is_null()
460 );
461 }
462
463 #[test]
467 #[should_panic(
468 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
469 )]
470 fn test_append_mask_wrong_length_panics() {
471 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
472 let mut range = builder.uninit_range(5);
473
474 let wrong_mask = Mask::from_iter([true, false, true]);
476
477 unsafe {
479 range.append_mask(&wrong_mask);
480 }
481 }
482
483 #[test]
487 fn test_copy_from_slice_with_offsets() {
488 let mut ctx = array_session().create_execution_ctx();
489 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
490 let mut range = builder.uninit_range(6);
491
492 range.copy_from_slice(0, &[1, 2]);
494 range.copy_from_slice(2, &[3, 4]);
495 range.copy_from_slice(4, &[5, 6]);
496
497 unsafe {
499 range.finish();
500 }
501
502 let array = builder.finish_into_primitive();
503 assert_arrays_eq!(
504 array,
505 PrimitiveArray::from_iter([1i32, 2, 3, 4, 5, 6]),
506 &mut ctx
507 );
508 }
509
510 #[test]
516 fn test_set_bit_relative_indexing() {
517 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
518
519 builder.append_value(100);
521 builder.append_value(200);
522
523 let mut range = builder.uninit_range(3);
525
526 let initial_mask = Mask::from_iter([false, false, false]);
528 unsafe {
530 range.append_mask(&initial_mask);
531 }
532
533 range.set_validity_bit(0, true); range.set_validity_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
540
541 unsafe {
543 range.finish();
544 }
545
546 let array = builder.finish_into_primitive();
547
548 assert_eq!(array.len(), 5);
550 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
551
552 assert!(
554 !array
555 .execute_scalar(0, &mut array_session().create_execution_ctx())
556 .unwrap()
557 .is_null()
558 ); assert!(
560 !array
561 .execute_scalar(1, &mut array_session().create_execution_ctx())
562 .unwrap()
563 .is_null()
564 ); assert!(
568 !array
569 .execute_scalar(2, &mut array_session().create_execution_ctx())
570 .unwrap()
571 .is_null()
572 ); assert!(
574 array
575 .execute_scalar(3, &mut array_session().create_execution_ctx())
576 .unwrap()
577 .is_null()
578 ); assert!(
580 !array
581 .execute_scalar(4, &mut array_session().create_execution_ctx())
582 .unwrap()
583 .is_null()
584 ); }
586
587 #[test]
589 #[should_panic(expected = "cannot create an uninit range of length 0")]
590 fn test_zero_length_uninit_range_panics() {
591 let mut builder = PrimitiveBuilder::<i32>::new(Nullability::NonNullable);
592 let _range = builder.uninit_range(0);
593 }
594
595 #[test]
597 #[should_panic(expected = "uninit_range of len 261 exceeds builder with length 0 and capacity")]
598 fn test_uninit_range_exceeds_capacity_panics() {
599 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 5);
600 let _range = builder.uninit_range(261);
601 }
602
603 #[test]
607 #[cfg(debug_assertions)]
608 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
609 fn test_copy_from_slice_out_of_bounds() {
610 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
611 let mut range = builder.uninit_range(3);
612
613 range.copy_from_slice(1, &[1, 2, 3]);
615 }
616
617 #[test]
621 fn test_finish_unsafe_contract() {
622 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
623 let mut range = builder.uninit_range(3);
624
625 let mask = Mask::from_iter([true, true, false]);
627 unsafe {
629 range.append_mask(&mask);
630 }
631
632 range.copy_from_slice(0, &[10, 20, 30]);
634
635 unsafe {
637 range.finish();
638 }
639
640 let array = builder.finish_into_primitive();
641 assert_eq!(array.len(), 3);
642 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
643 }
644
645 #[test]
646 fn test_append_scalar() {
647 use crate::dtype::DType;
648 use crate::scalar::Scalar;
649
650 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
651
652 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
654 builder.append_scalar(&scalar1).unwrap();
655
656 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
658 builder.append_scalar(&scalar2).unwrap();
659
660 let null_scalar = Scalar::null(DType::Primitive(
662 crate::dtype::PType::I32,
663 Nullability::Nullable,
664 ));
665 builder.append_scalar(&null_scalar).unwrap();
666
667 let array = builder.finish_into_primitive();
668 assert_eq!(array.len(), 3);
669
670 let values = array.as_slice::<i32>();
672 assert_eq!(values[0], 42);
673 assert_eq!(values[1], 84);
674 let mut ctx = array_session().create_execution_ctx();
678 assert!(
679 array
680 .validity()
681 .vortex_expect("primitive validity should be derivable")
682 .execute_is_valid(0, &mut ctx)
683 .unwrap()
684 );
685 assert!(
686 array
687 .validity()
688 .vortex_expect("primitive validity should be derivable")
689 .execute_is_valid(1, &mut ctx)
690 .unwrap()
691 );
692 assert!(
693 !array
694 .validity()
695 .vortex_expect("primitive validity should be derivable")
696 .execute_is_valid(2, &mut ctx)
697 .unwrap()
698 );
699
700 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
702 let wrong_scalar = Scalar::from(true);
703 assert!(builder.append_scalar(&wrong_scalar).is_err());
704 }
705}