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 values(&self) -> &[T] {
56 self.values.as_ref()
57 }
58
59 pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
93 assert_ne!(0, len, "cannot create an uninit range of length 0");
94
95 let current_len = self.values.len();
96 assert!(
97 current_len + len <= self.values.capacity(),
98 "uninit_range of len {len} exceeds builder with length {} and capacity {}",
99 current_len,
100 self.values.capacity()
101 );
102
103 UninitRange { len, builder: self }
104 }
105
106 pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
108 let validity = self
109 .nulls
110 .finish_with_nullability(self.dtype().nullability());
111
112 PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
113 }
114
115 pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: Mask) {
117 self.values.extend(iter);
118 self.nulls.append_validity_mask(mask);
119 }
120}
121
122impl<T: NativePType> ArrayBuilder for PrimitiveBuilder<T> {
123 fn as_any(&self) -> &dyn Any {
124 self
125 }
126
127 fn as_any_mut(&mut self) -> &mut dyn Any {
128 self
129 }
130
131 fn dtype(&self) -> &DType {
132 &self.dtype
133 }
134
135 fn len(&self) -> usize {
136 self.values.len()
137 }
138
139 fn append_zeros(&mut self, n: usize) {
140 self.values.push_n(T::default(), n);
141 self.nulls.append_n_non_nulls(n);
142 }
143
144 unsafe fn append_nulls_unchecked(&mut self, n: usize) {
145 self.values.push_n(T::default(), n);
146 self.nulls.append_n_nulls(n);
147 }
148
149 fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
150 vortex_ensure!(
151 scalar.dtype() == self.dtype(),
152 "PrimitiveBuilder expected scalar with dtype {}, got {}",
153 self.dtype(),
154 scalar.dtype()
155 );
156
157 if let Some(pv) = scalar.as_primitive().pvalue() {
158 self.append_value(pv.cast::<T>()?)
159 } else {
160 self.append_null()
161 }
162
163 Ok(())
164 }
165
166 unsafe fn extend_from_array_unchecked(&mut self, array: &ArrayRef) {
167 let array = array.to_primitive();
168
169 debug_assert_eq!(
171 array.ptype(),
172 T::PTYPE,
173 "Cannot extend from array with different ptype"
174 );
175
176 self.values.extend_from_slice(array.as_slice::<T>());
177 self.nulls.append_validity_mask(
178 array
179 .validity_mask()
180 .vortex_expect("validity_mask in extend_from_array_unchecked"),
181 );
182 }
183
184 fn reserve_exact(&mut self, additional: usize) {
185 self.values.reserve(additional);
186 self.nulls.reserve_exact(additional);
187 }
188
189 unsafe fn set_validity_unchecked(&mut self, validity: Mask) {
190 self.nulls = LazyBitBufferBuilder::new(validity.len());
191 self.nulls.append_validity_mask(validity);
192 }
193
194 fn finish(&mut self) -> ArrayRef {
195 self.finish_into_primitive().into_array()
196 }
197
198 fn finish_into_canonical(&mut self) -> Canonical {
199 Canonical::Primitive(self.finish_into_primitive())
200 }
201}
202
203pub struct UninitRange<'a, T> {
205 len: usize,
209
210 builder: &'a mut PrimitiveBuilder<T>,
215}
216
217impl<T> UninitRange<'_, T> {
218 #[inline]
220 pub fn len(&self) -> usize {
221 self.len
222 }
223
224 #[inline]
226 pub fn is_empty(&self) -> bool {
227 self.len == 0
228 }
229
230 #[inline]
236 pub fn set_value(&mut self, index: usize, value: T) {
237 assert!(index < self.len, "index out of bounds");
238 let spare = self.builder.values.spare_capacity_mut();
239 spare[index] = MaybeUninit::new(value);
240 }
241
242 pub unsafe fn append_mask(&mut self, mask: Mask) {
254 assert_eq!(
255 mask.len(),
256 self.len,
257 "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
258 );
259
260 self.builder.nulls.append_validity_mask(mask);
265 }
266
267 pub fn set_validity_bit(&mut self, index: usize, v: bool) {
274 assert!(index < self.len, "set_bit index out of bounds");
275 let absolute_index = self.builder.values.len() + index;
278 self.builder.nulls.set_bit(absolute_index, v);
279 }
280
281 pub fn copy_from_slice(&mut self, local_offset: usize, src: &[T])
286 where
287 T: Copy,
288 {
289 debug_assert!(
290 local_offset + src.len() <= self.len,
291 "tried to copy a slice into a `UninitRange` past its boundary"
292 );
293
294 let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
296
297 let dst =
300 &mut self.builder.values.spare_capacity_mut()[local_offset..local_offset + src.len()];
301 dst.copy_from_slice(uninit_src);
302 }
303
304 pub unsafe fn slice_uninit_mut(&mut self, offset: usize, len: usize) -> &mut [MaybeUninit<T>] {
318 assert!(
319 offset + len <= self.len,
320 "slice_uninit_mut: offset {} + len {} exceeds range length {}",
321 offset,
322 len,
323 self.len
324 );
325 &mut self.builder.values.spare_capacity_mut()[offset..offset + len]
326 }
327
328 pub unsafe fn finish(self) {
342 let new_len = self.builder.values.len() + self.len;
344 unsafe { self.builder.values.set_len(new_len) };
345 }
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351 use crate::assert_arrays_eq;
352
353 #[test]
358 fn test_multiple_uninit_ranges_correct_offsets() {
359 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
360
361 let mut range1 = builder.uninit_range(3);
363 range1.copy_from_slice(0, &[1, 2, 3]);
364
365 unsafe {
367 range1.finish();
368 }
369
370 assert_eq!(builder.values(), &[1, 2, 3]);
372
373 let mut range2 = builder.uninit_range(2);
375
376 range2.copy_from_slice(0, &[4, 5]);
378
379 unsafe {
381 range2.finish();
382 }
383
384 assert_eq!(builder.values(), &[1, 2, 3, 4, 5]);
386
387 let array = builder.finish_into_primitive();
388 assert_arrays_eq!(array, PrimitiveArray::from_iter([1i32, 2, 3, 4, 5]));
389 }
390
391 #[test]
397 fn test_append_mask_on_uninit_range() {
398 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
399 let mut range = builder.uninit_range(3);
400
401 let mask = Mask::from_iter([true, false, true]);
403
404 unsafe {
406 range.append_mask(mask);
407 }
408
409 range.copy_from_slice(0, &[10, 20, 30]);
411
412 unsafe {
414 range.finish();
415 }
416
417 let array = builder.finish_into_primitive();
418 assert_eq!(array.len(), 3);
419 assert!(!array.scalar_at(0).unwrap().is_null());
421 assert!(array.scalar_at(1).unwrap().is_null());
422 assert!(!array.scalar_at(2).unwrap().is_null());
423 }
424
425 #[test]
429 #[should_panic(
430 expected = "Tried to append a mask to an `UninitRange` that was beyond the allowed range"
431 )]
432 fn test_append_mask_wrong_length_panics() {
433 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
434 let mut range = builder.uninit_range(5);
435
436 let wrong_mask = Mask::from_iter([true, false, true]);
438
439 unsafe {
441 range.append_mask(wrong_mask);
442 }
443 }
444
445 #[test]
449 fn test_copy_from_slice_with_offsets() {
450 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
451 let mut range = builder.uninit_range(6);
452
453 range.copy_from_slice(0, &[1, 2]);
455 range.copy_from_slice(2, &[3, 4]);
456 range.copy_from_slice(4, &[5, 6]);
457
458 unsafe {
460 range.finish();
461 }
462
463 let array = builder.finish_into_primitive();
464 assert_arrays_eq!(array, PrimitiveArray::from_iter([1i32, 2, 3, 4, 5, 6]));
465 }
466
467 #[test]
473 fn test_set_bit_relative_indexing() {
474 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
475
476 builder.append_value(100);
478 builder.append_value(200);
479
480 let mut range = builder.uninit_range(3);
482
483 let initial_mask = Mask::from_iter([false, false, false]);
485 unsafe {
487 range.append_mask(initial_mask);
488 }
489
490 range.set_validity_bit(0, true); range.set_validity_bit(2, true); range.copy_from_slice(0, &[10, 20, 30]);
497
498 unsafe {
500 range.finish();
501 }
502
503 let array = builder.finish_into_primitive();
504
505 assert_eq!(array.len(), 5);
507 assert_eq!(array.as_slice::<i32>(), &[100, 200, 10, 20, 30]);
508
509 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()); }
518
519 #[test]
521 #[should_panic(expected = "cannot create an uninit range of length 0")]
522 fn test_zero_length_uninit_range_panics() {
523 let mut builder = PrimitiveBuilder::<i32>::new(Nullability::NonNullable);
524 let _range = builder.uninit_range(0);
525 }
526
527 #[test]
529 #[should_panic(
530 expected = "uninit_range of len 10 exceeds builder with length 0 and capacity 6"
531 )]
532 fn test_uninit_range_exceeds_capacity_panics() {
533 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 5);
534 let _range = builder.uninit_range(10);
535 }
536
537 #[test]
541 #[cfg(debug_assertions)]
542 #[should_panic(expected = "tried to copy a slice into a `UninitRange` past its boundary")]
543 fn test_copy_from_slice_out_of_bounds() {
544 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
545 let mut range = builder.uninit_range(3);
546
547 range.copy_from_slice(1, &[1, 2, 3]);
549 }
550
551 #[test]
555 fn test_finish_unsafe_contract() {
556 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 5);
557 let mut range = builder.uninit_range(3);
558
559 let mask = Mask::from_iter([true, true, false]);
561 unsafe {
563 range.append_mask(mask);
564 }
565
566 range.copy_from_slice(0, &[10, 20, 30]);
568
569 unsafe {
571 range.finish();
572 }
573
574 let array = builder.finish_into_primitive();
575 assert_eq!(array.len(), 3);
576 assert_eq!(array.as_slice::<i32>(), &[10, 20, 30]);
577 }
578
579 #[test]
580 fn test_append_scalar() {
581 use crate::dtype::DType;
582 use crate::scalar::Scalar;
583
584 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::Nullable, 10);
585
586 let scalar1 = Scalar::primitive(42i32, Nullability::Nullable);
588 builder.append_scalar(&scalar1).unwrap();
589
590 let scalar2 = Scalar::primitive(84i32, Nullability::Nullable);
592 builder.append_scalar(&scalar2).unwrap();
593
594 let null_scalar = Scalar::null(DType::Primitive(
596 crate::dtype::PType::I32,
597 Nullability::Nullable,
598 ));
599 builder.append_scalar(&null_scalar).unwrap();
600
601 let array = builder.finish_into_primitive();
602 assert_eq!(array.len(), 3);
603
604 let values = array.as_slice::<i32>();
606 assert_eq!(values[0], 42);
607 assert_eq!(values[1], 84);
608 use crate::vtable::ValidityHelper;
612 assert!(array.validity().is_valid(0).unwrap());
613 assert!(array.validity().is_valid(1).unwrap());
614 assert!(!array.validity().is_valid(2).unwrap());
615
616 let mut builder = PrimitiveBuilder::<i32>::with_capacity(Nullability::NonNullable, 10);
618 let wrong_scalar = Scalar::from(true);
619 assert!(builder.append_scalar(&wrong_scalar).is_err());
620 }
621}