1use std::any::Any;
5use std::mem::MaybeUninit;
6
7use vortex_buffer::BufferMut;
8use vortex_dtype::{DType, NativePType, Nullability};
9use vortex_error::{VortexResult, vortex_ensure};
10use vortex_mask::Mask;
11use vortex_scalar::{PrimitiveScalar, Scalar};
12
13use crate::arrays::PrimitiveArray;
14use crate::builders::{ArrayBuilder, DEFAULT_BUILDER_CAPACITY, LazyNullBufferBuilder};
15use crate::canonical::{Canonical, ToCanonical};
16use crate::{Array, ArrayRef, IntoArray};
17
18pub struct PrimitiveBuilder<T> {
20 dtype: DType,
21 values: BufferMut<T>,
22 nulls: LazyNullBufferBuilder,
23}
24
25impl<T: NativePType> PrimitiveBuilder<T> {
26 pub fn new(nullability: Nullability) -> Self {
28 Self::with_capacity(nullability, DEFAULT_BUILDER_CAPACITY)
29 }
30
31 pub fn with_capacity(nullability: Nullability, capacity: usize) -> Self {
33 Self {
34 values: BufferMut::with_capacity(capacity),
35 nulls: LazyNullBufferBuilder::new(capacity),
36 dtype: DType::Primitive(T::PTYPE, nullability),
37 }
38 }
39
40 pub fn append_value(&mut self, value: T) {
42 self.values.push(value);
43 self.nulls.append_non_null();
44 }
45
46 pub fn values(&self) -> &[T] {
48 self.values.as_ref()
49 }
50
51 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
85 assert_ne!(0, len, "cannot create an uninit range of length 0");
86
87 let current_len = self.values.len();
88 assert!(
89 current_len + len <= self.values.capacity(),
90 "uninit_range of len {len} exceeds builder capacity {}",
91 self.values.capacity()
92 );
93
94 UninitRange { len, builder: self }
95 }
96
97 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
99 let validity = self
100 .nulls
101 .finish_with_nullability(self.dtype().nullability());
102
103 PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
104 }
105
106 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: Mask) {
108 self.values.extend(iter);
109 self.nulls.append_validity_mask(mask);
110 }
111}
112
113impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
114 fn as_any(&self) -> &dyn Any {
115 self
116 }
117
118 fn as_any_mut(&mut self) -> &mut dyn Any {
119 self
120 }
121
122 fn dtype(&self) -> &DType {
123 &self.dtype
124 }
125
126 fn len(&self) -> usize {
127 self.values.len()
128 }
129
130 fn append_zeros(&mut self, n: usize) {
131 self.values.push_n(T::default(), n);
132 self.nulls.append_n_non_nulls(n);
133 }
134
135 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
136 self.values.push_n(T::default(), n);
137 self.nulls.append_n_nulls(n);
138 }
139
140 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
141 vortex_ensure!(
142 scalar.dtype() == self.dtype(),
143 "PrimitiveBuilder expected scalar with dtype {:?}, got {:?}",
144 self.dtype(),
145 scalar.dtype()
146 );
147
148 let primitive_scalar = PrimitiveScalar::try_from(scalar)?;
149 match primitive_scalar.pvalue() {
150 Some(pv) => self.append_value(pv.as_primitive::<T>()),
151 None => self.append_null(),
152 }
153
154 Ok(())
155 }
156
157 unsafe fn extend_from_array_unchecked(&mut self, array: &dyn Array) {
158 let array = array.to_primitive();
159
160 debug_assert_eq!(
162 array.ptype(),
163 T::PTYPE,
164 "Cannot extend from array with different ptype"
165 );
166
167 self.values.extend_from_slice(array.as_slice::<T>());
168 self.nulls.append_validity_mask(array.validity_mask());
169 }
170
171 fn ensure_capacity(&mut self, capacity: usize) {
172 if capacity > self.values.capacity() {
173 self.values.reserve(capacity - self.values.len());
174 self.nulls.ensure_capacity(capacity);
175 }
176 }
177
178 fn set_validity(&mut self, validity: Mask) {
179 self.nulls = LazyNullBufferBuilder::new(validity.len());
180 self.nulls.append_validity_mask(validity);
181 }
182
183 fn finish(&mut self) -> ArrayRef {
184 self.finish_into_primitive().into_array()
185 }
186
187 fn finish_into_canonical(&mut self) -> Canonical {
188 Canonical::Primitive(self.finish_into_primitive())
189 }
190}
191
192pub struct UninitRange<'a, T> {
194 len: usize,
198
199 builder: &'a mut PrimitiveBuilder<T>,
204}
205
206impl<T> UninitRange<'_, T> {
207 #[inline]
209 pub fn len(&self) -> usize {
210 self.len
211 }
212
213 #[inline]
215 pub fn is_empty(&self) -> bool {
216 self.len == 0
217 }
218
219 #[inline]
225 pub fn set_value(&mut self, index: usize, value: T) {
226 assert!(index < self.len, "index out of bounds");
227 let spare = self.builder.values.spare_capacity_mut();
228 spare[index] = MaybeUninit::new(value);
229 }
230
231 pub unsafe fn append_mask(&mut self, mask: Mask) {
243 assert_eq!(
244 mask.len(),
245 self.len,
246 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
247 );
248
249 self.builder.nulls.append_validity_mask(mask);
254 }
255
256 pub fn set_bit(&mut self, index: usize, v: bool) {
263 assert!(index < self.len, "set_bit index out of bounds");
264 let absolute_index = self.builder.values.len() + index;
267 self.builder.nulls.set_bit(absolute_index, v);
268 }
269
270 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
275 where
276 T: Copy,
277 {
278 debug_assert!(
279 local_offset + src.len() <= self.len,
280 "tried to copy a slice into a `UninitRange` past its boundary"
281 );
282
283 let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
285
286 let dst =
289 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
290 dst.copy_from_slice(uninit_src);
291 }
292
293 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
307 assert!(
308 offset + len <= self.len,
309 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
310 offset,
311 len,
312 self.len
313 );
314 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
315 }
316
317 pub unsafe fn finish(self) {
329 let new_len = self.builder.values.len() + self.len;
331 unsafe { self.builder.values.set_len(new_len) };
332 }
333}
334
335#[cfg(test)]
336mod tests {
337 use super::*;
338
339 #[test]
344 fn test_multiple_uninit_ranges_correct_offsets() {
345 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
346
347 let mut range1 = builder.uninit_range(3);
349 range1.copy_from_slice(0, &[1, 2, 3]);
350
351 unsafe {
353 range1.finish();
354 }
355
356 assert_eq!(builder.values(), &[1, 2, 3]);
358
359 let mut range2 = builder.uninit_range(2);
361
362 range2.copy_from_slice(0, &[4, 5]);
364
365 unsafe {
367 range2.finish();
368 }
369
370 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
372
373 let array = builder.finish_into_primitive();
374 assert_eq!(array.as_slice::<i32>(), &[1, 2, 3, 4, 5]);
375 }
376
377 #[test]
383 fn test_append_mask_on_uninit_range() {
384 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
385 let mut range = builder.uninit_range(3);
386
387 let mask = Mask::from_iter([true, false, true]);
389
390 unsafe {
392 range.append_mask(mask);
393 }
394
395 range.copy_from_slice(0, &[10, 20, 30]);
397
398 unsafe {
400 range.finish();
401 }
402
403 let array = builder.finish_into_primitive();
404 assert_eq!(array.len(), 3);
405 assert!(!array.scalar_at(0).is_null());
407 assert!(array.scalar_at(1).is_null());
408 assert!(!array.scalar_at(2).is_null());
409 }
410
411 #[test]
415 #[should_panic(
416 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
417 )]
418 fn test_append_mask_wrong_length_panics() {
419 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
420 let mut range = builder.uninit_range(5);
421
422 let wrong_mask = Mask::from_iter([true, false, true]);
424
425 unsafe {
427 range.append_mask(wrong_mask);
428 }
429 }
430
431 #[test]
435 fn test_copy_from_slice_with_offsets() {
436 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
437 let mut range = builder.uninit_range(6);
438
439 range.copy_from_slice(0, &[1, 2]);
441 range.copy_from_slice(2, &[3, 4]);
442 range.copy_from_slice(4, &[5, 6]);
443
444 unsafe {
446 range.finish();
447 }
448
449 let array = builder.finish_into_primitive();
450 assert_eq!(array.as_slice::<i32>(), &[1, 2, 3, 4, 5, 6]);
451 }
452
453 #[test]
459 fn test_set_bit_relative_indexing() {
460 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
461
462 builder.append_value(100);
464 builder.append_value(200);
465
466 let mut range = builder.uninit_range(3);
468
469 let initial_mask = Mask::from_iter([false, false, false]);
471 unsafe {
473 range.append_mask(initial_mask);
474 }
475
476 range.set_bit(0, true); range.set_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
483
484 unsafe {
486 range.finish();
487 }
488
489 let array = builder.finish_into_primitive();
490
491 assert_eq!(array.len(), 5);
493 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
494
495 assert!(!array.scalar_at(0).is_null()); assert!(!array.scalar_at(1).is_null()); assert!(!array.scalar_at(2).is_null()); assert!(array.scalar_at(3).is_null()); assert!(!array.scalar_at(4).is_null()); }
504
505 #[test]
507 #[should_panic(expected = "cannot create an uninit range of length 0")]
508 fn test_zero_length_uninit_range_panics() {
509 let mut builder = PrimitiveBuilder::<i32>::new(Nullability::NonNullable);
510 let _range = builder.uninit_range(0);
511 }
512
513 #[test]
515 #[should_panic(expected = "uninit_range of len 10 exceeds builder capacity")]
516 fn test_uninit_range_exceeds_capacity_panics() {
517 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 5);
518 let _range = builder.uninit_range(10);
519 }
520
521 #[test]
525 #[cfg(debug_assertions)]
526 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
527 fn test_copy_from_slice_out_of_bounds() {
528 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
529 let mut range = builder.uninit_range(3);
530
531 range.copy_from_slice(1, &[1, 2, 3]);
533 }
534
535 #[test]
539 fn test_finish_unsafe_contract() {
540 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
541 let mut range = builder.uninit_range(3);
542
543 let mask = Mask::from_iter([true, true, false]);
545 unsafe {
547 range.append_mask(mask);
548 }
549
550 range.copy_from_slice(0, &[10, 20, 30]);
552
553 unsafe {
555 range.finish();
556 }
557
558 let array = builder.finish_into_primitive();
559 assert_eq!(array.len(), 3);
560 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
561 }
562
563 #[test]
564 fn test_append_scalar() {
565 use vortex_dtype::DType;
566 use vortex_scalar::Scalar;
567
568 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
569
570 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
572 builder.append_scalar(&scalar1).unwrap();
573
574 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
576 builder.append_scalar(&scalar2).unwrap();
577
578 let null_scalar = Scalar::null(DType::Primitive(
580 vortex_dtype::PType::I32,
581 Nullability::Nullable,
582 ));
583 builder.append_scalar(&null_scalar).unwrap();
584
585 let array = builder.finish_into_primitive();
586 assert_eq!(array.len(), 3);
587
588 let values = array.as_slice::<i32>();
590 assert_eq!(values[0], 42);
591 assert_eq!(values[1], 84);
592 use crate::vtable::ValidityHelper;
596 assert!(array.validity().is_valid(0));
597 assert!(array.validity().is_valid(1));
598 assert!(!array.validity().is_valid(2));
599
600 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
602 let wrong_scalar = Scalar::from(true);
603 assert!(builder.append_scalar(&wrong_scalar).is_err());
604 }
605}