1use std::any::Any;
5use std::mem::MaybeUninit;
6
7use vortex_buffer::BufferMut;
8use vortex_dtype::DType;
9use vortex_dtype::NativePType;
10use vortex_dtype::Nullability;
11use vortex_error::VortexResult;
12use vortex_error::vortex_ensure;
13use vortex_mask::Mask;
14use vortex_scalar::PrimitiveScalar;
15use vortex_scalar::Scalar;
16
17use crate::Array;
18use crate::ArrayRef;
19use crate::IntoArray;
20use crate::arrays::PrimitiveArray;
21use crate::builders::ArrayBuilder;
22use crate::builders::DEFAULT_BUILDER_CAPACITY;
23use crate::builders::LazyBitBufferBuilder;
24use crate::canonical::Canonical;
25use crate::canonical::ToCanonical;
26
27pub struct PrimitiveBuilder<T> {
29 dtype: DType,
30 values: BufferMut<T>,
31 nulls: LazyBitBufferBuilder,
32}
33
34impl<T: NativePType> PrimitiveBuilder<T> {
35 pub fn new(nullability: Nullability) -> Self {
37 Self::with_capacity(nullability, DEFAULT_BUILDER_CAPACITY)
38 }
39
40 pub fn with_capacity(nullability: Nullability, capacity: usize) -> Self {
42 Self {
43 values: BufferMut::with_capacity(capacity),
44 nulls: LazyBitBufferBuilder::new(capacity),
45 dtype: DType::Primitive(T::PTYPE, nullability),
46 }
47 }
48
49 pub fn append_value(&mut self, value: T) {
51 self.values.push(value);
52 self.nulls.append_non_null();
53 }
54
55 pub fn values(&self) -> &[T] {
57 self.values.as_ref()
58 }
59
60 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
94 assert_ne!(0, len, "cannot create an uninit range of length 0");
95
96 let current_len = self.values.len();
97 assert!(
98 current_len + len <= self.values.capacity(),
99 "uninit_range of len {len} exceeds builder with length {} and capacity {}",
100 current_len,
101 self.values.capacity()
102 );
103
104 UninitRange { len, builder: self }
105 }
106
107 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
109 let validity = self
110 .nulls
111 .finish_with_nullability(self.dtype().nullability());
112
113 PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
114 }
115
116 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: Mask) {
118 self.values.extend(iter);
119 self.nulls.append_validity_mask(mask);
120 }
121}
122
123impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
124 fn as_any(&self) -> &dyn Any {
125 self
126 }
127
128 fn as_any_mut(&mut self) -> &mut dyn Any {
129 self
130 }
131
132 fn dtype(&self) -> &DType {
133 &self.dtype
134 }
135
136 fn len(&self) -> usize {
137 self.values.len()
138 }
139
140 fn append_zeros(&mut self, n: usize) {
141 self.values.push_n(T::default(), n);
142 self.nulls.append_n_non_nulls(n);
143 }
144
145 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
146 self.values.push_n(T::default(), n);
147 self.nulls.append_n_nulls(n);
148 }
149
150 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
151 vortex_ensure!(
152 scalar.dtype() == self.dtype(),
153 "PrimitiveBuilder expected scalar with dtype {:?}, got {:?}",
154 self.dtype(),
155 scalar.dtype()
156 );
157
158 let primitive_scalar = PrimitiveScalar::try_from(scalar)?;
159 match primitive_scalar.pvalue() {
160 Some(pv) => self.append_value(pv.cast::<T>()),
161 None => self.append_null(),
162 }
163
164 Ok(())
165 }
166
167 unsafe fn extend_from_array_unchecked(&mut self, array: &dyn Array) {
168 let array = array.to_primitive();
169
170 debug_assert_eq!(
172 array.ptype(),
173 T::PTYPE,
174 "Cannot extend from array with different ptype"
175 );
176
177 self.values.extend_from_slice(array.as_slice::<T>());
178 self.nulls.append_validity_mask(array.validity_mask());
179 }
180
181 fn reserve_exact(&mut self, additional: usize) {
182 self.values.reserve(additional);
183 self.nulls.reserve_exact(additional);
184 }
185
186 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
187 self.nulls = LazyBitBufferBuilder::new(validity.len());
188 self.nulls.append_validity_mask(validity);
189 }
190
191 fn finish(&mut self) -> ArrayRef {
192 self.finish_into_primitive().into_array()
193 }
194
195 fn finish_into_canonical(&mut self) -> Canonical {
196 Canonical::Primitive(self.finish_into_primitive())
197 }
198}
199
200pub struct UninitRange<'a, T> {
202 len: usize,
206
207 builder: &'a mut PrimitiveBuilder<T>,
212}
213
214impl<T> UninitRange<'_, T> {
215 #[inline]
217 pub fn len(&self) -> usize {
218 self.len
219 }
220
221 #[inline]
223 pub fn is_empty(&self) -> bool {
224 self.len == 0
225 }
226
227 #[inline]
233 pub fn set_value(&mut self, index: usize, value: T) {
234 assert!(index < self.len, "index out of bounds");
235 let spare = self.builder.values.spare_capacity_mut();
236 spare[index] = MaybeUninit::new(value);
237 }
238
239 pub unsafe fn append_mask(&mut self, mask: Mask) {
251 assert_eq!(
252 mask.len(),
253 self.len,
254 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
255 );
256
257 self.builder.nulls.append_validity_mask(mask);
262 }
263
264 pub fn set_validity_bit(&mut self, index: usize, v: bool) {
271 assert!(index < self.len, "set_bit index out of bounds");
272 let absolute_index = self.builder.values.len() + index;
275 self.builder.nulls.set_bit(absolute_index, v);
276 }
277
278 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
283 where
284 T: Copy,
285 {
286 debug_assert!(
287 local_offset + src.len() <= self.len,
288 "tried to copy a slice into a `UninitRange` past its boundary"
289 );
290
291 let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
293
294 let dst =
297 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
298 dst.copy_from_slice(uninit_src);
299 }
300
301 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
315 assert!(
316 offset + len <= self.len,
317 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
318 offset,
319 len,
320 self.len
321 );
322 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
323 }
324
325 pub unsafe fn finish(self) {
339 let new_len = self.builder.values.len() + self.len;
341 unsafe { self.builder.values.set_len(new_len) };
342 }
343}
344
345#[cfg(test)]
346mod tests {
347 use super::*;
348
349 #[test]
354 fn test_multiple_uninit_ranges_correct_offsets() {
355 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
356
357 let mut range1 = builder.uninit_range(3);
359 range1.copy_from_slice(0, &[1, 2, 3]);
360
361 unsafe {
363 range1.finish();
364 }
365
366 assert_eq!(builder.values(), &[1, 2, 3]);
368
369 let mut range2 = builder.uninit_range(2);
371
372 range2.copy_from_slice(0, &[4, 5]);
374
375 unsafe {
377 range2.finish();
378 }
379
380 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
382
383 let array = builder.finish_into_primitive();
384 assert_eq!(array.as_slice::<i32>(), &[1, 2, 3, 4, 5]);
385 }
386
387 #[test]
393 fn test_append_mask_on_uninit_range() {
394 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
395 let mut range = builder.uninit_range(3);
396
397 let mask = Mask::from_iter([true, false, true]);
399
400 unsafe {
402 range.append_mask(mask);
403 }
404
405 range.copy_from_slice(0, &[10, 20, 30]);
407
408 unsafe {
410 range.finish();
411 }
412
413 let array = builder.finish_into_primitive();
414 assert_eq!(array.len(), 3);
415 assert!(!array.scalar_at(0).is_null());
417 assert!(array.scalar_at(1).is_null());
418 assert!(!array.scalar_at(2).is_null());
419 }
420
421 #[test]
425 #[should_panic(
426 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
427 )]
428 fn test_append_mask_wrong_length_panics() {
429 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
430 let mut range = builder.uninit_range(5);
431
432 let wrong_mask = Mask::from_iter([true, false, true]);
434
435 unsafe {
437 range.append_mask(wrong_mask);
438 }
439 }
440
441 #[test]
445 fn test_copy_from_slice_with_offsets() {
446 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
447 let mut range = builder.uninit_range(6);
448
449 range.copy_from_slice(0, &[1, 2]);
451 range.copy_from_slice(2, &[3, 4]);
452 range.copy_from_slice(4, &[5, 6]);
453
454 unsafe {
456 range.finish();
457 }
458
459 let array = builder.finish_into_primitive();
460 assert_eq!(array.as_slice::<i32>(), &[1, 2, 3, 4, 5, 6]);
461 }
462
463 #[test]
469 fn test_set_bit_relative_indexing() {
470 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
471
472 builder.append_value(100);
474 builder.append_value(200);
475
476 let mut range = builder.uninit_range(3);
478
479 let initial_mask = Mask::from_iter([false, false, false]);
481 unsafe {
483 range.append_mask(initial_mask);
484 }
485
486 range.set_validity_bit(0, true); range.set_validity_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
493
494 unsafe {
496 range.finish();
497 }
498
499 let array = builder.finish_into_primitive();
500
501 assert_eq!(array.len(), 5);
503 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
504
505 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()); }
514
515 #[test]
517 #[should_panic(expected = "cannot create an uninit range of length 0")]
518 fn test_zero_length_uninit_range_panics() {
519 let mut builder = PrimitiveBuilder::<i32>::new(Nullability::NonNullable);
520 let _range = builder.uninit_range(0);
521 }
522
523 #[test]
525 #[should_panic(
526 expected = "uninit_range of len 10 exceeds builder with length 0 and capacity 6"
527 )]
528 fn test_uninit_range_exceeds_capacity_panics() {
529 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 5);
530 let _range = builder.uninit_range(10);
531 }
532
533 #[test]
537 #[cfg(debug_assertions)]
538 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
539 fn test_copy_from_slice_out_of_bounds() {
540 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
541 let mut range = builder.uninit_range(3);
542
543 range.copy_from_slice(1, &[1, 2, 3]);
545 }
546
547 #[test]
551 fn test_finish_unsafe_contract() {
552 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
553 let mut range = builder.uninit_range(3);
554
555 let mask = Mask::from_iter([true, true, false]);
557 unsafe {
559 range.append_mask(mask);
560 }
561
562 range.copy_from_slice(0, &[10, 20, 30]);
564
565 unsafe {
567 range.finish();
568 }
569
570 let array = builder.finish_into_primitive();
571 assert_eq!(array.len(), 3);
572 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
573 }
574
575 #[test]
576 fn test_append_scalar() {
577 use vortex_dtype::DType;
578 use vortex_scalar::Scalar;
579
580 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
581
582 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
584 builder.append_scalar(&scalar1).unwrap();
585
586 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
588 builder.append_scalar(&scalar2).unwrap();
589
590 let null_scalar = Scalar::null(DType::Primitive(
592 vortex_dtype::PType::I32,
593 Nullability::Nullable,
594 ));
595 builder.append_scalar(&null_scalar).unwrap();
596
597 let array = builder.finish_into_primitive();
598 assert_eq!(array.len(), 3);
599
600 let values = array.as_slice::<i32>();
602 assert_eq!(values[0], 42);
603 assert_eq!(values[1], 84);
604 use crate::vtable::ValidityHelper;
608 assert!(array.validity().is_valid(0));
609 assert!(array.validity().is_valid(1));
610 assert!(!array.validity().is_valid(2));
611
612 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
614 let wrong_scalar = Scalar::from(true);
615 assert!(builder.append_scalar(&wrong_scalar).is_err());
616 }
617}