• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16935267080

13 Aug 2025 11:00AM UTC coverage: 24.312% (-63.3%) from 87.658%
16935267080

Pull #4226

github

web-flow
Merge 81b48c7fb into baa6ea202
Pull Request #4226: Support converting TimestampTZ to and from duckdb

0 of 2 new or added lines in 1 file covered. (0.0%)

20666 existing lines in 469 files now uncovered.

8726 of 35892 relevant lines covered (24.31%)

147.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.75
/vortex-array/src/builders/primitive.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::any::Any;
5
use std::mem::MaybeUninit;
6
use std::ops::{Deref, DerefMut};
7

8
use vortex_buffer::BufferMut;
9
use vortex_dtype::{DType, NativePType, Nullability};
10
use vortex_error::{VortexResult, vortex_bail};
11
use vortex_mask::Mask;
12

13
use crate::arrays::PrimitiveArray;
14
use crate::builders::ArrayBuilder;
15
use crate::builders::lazy_validity_builder::LazyNullBufferBuilder;
16
use crate::{Array, ArrayRef, IntoArray, ToCanonical};
17

18
/// Builder for [`PrimitiveArray`].
19
pub struct PrimitiveBuilder<T> {
20
    values: BufferMut<T>,
21
    nulls: LazyNullBufferBuilder,
22
    dtype: DType,
23
}
24

25
impl<T: NativePType> PrimitiveBuilder<T> {
26
    pub fn new(nullability: Nullability) -> Self {
×
27
        Self::with_capacity(nullability, 1024) // Same as Arrow builders
×
28
    }
×
29

30
    pub fn with_capacity(nullability: Nullability, capacity: usize) -> Self {
56✔
31
        Self {
56✔
32
            values: BufferMut::with_capacity(capacity),
56✔
33
            nulls: LazyNullBufferBuilder::new(capacity),
56✔
34
            dtype: DType::Primitive(T::PTYPE, nullability),
56✔
35
        }
56✔
36
    }
56✔
37

38
    /// Append a `Mask` to the null buffer.
UNCOV
39
    pub fn append_mask(&mut self, mask: Mask) {
×
UNCOV
40
        self.nulls.append_validity_mask(mask);
×
UNCOV
41
    }
×
42

UNCOV
43
    pub fn append_value(&mut self, value: T) {
×
UNCOV
44
        self.values.push(value);
×
UNCOV
45
        self.nulls.append(true);
×
UNCOV
46
    }
×
47

48
    pub fn append_option(&mut self, value: Option<T>) {
72✔
49
        match value {
72✔
50
            Some(value) => {
72✔
51
                self.values.push(value);
72✔
52
                self.nulls.append(true);
72✔
53
            }
72✔
54
            None => self.append_null(),
×
55
        }
56
    }
72✔
57

58
    pub fn values(&self) -> &[T] {
×
59
        self.values.as_ref()
×
60
    }
×
61

62
    /// Create a new handle to the next `len` uninitialized values in the builder.
63
    ///
64
    /// All reads/writes through the handle to the values buffer or the validity buffer will operate
65
    /// on indices relative to the start of the range.
66
    ///
67
    ///
68
    /// ## Example
69
    ///
70
    /// ```
71
    /// use std::mem::MaybeUninit;
72
    /// use vortex_array::builders::{ArrayBuilder, PrimitiveBuilder};
73
    /// use vortex_dtype::Nullability;
74
    ///
75
    /// // Create a new builder.
76
    /// let mut builder: PrimitiveBuilder<i32> = PrimitiveBuilder::with_capacity(Nullability::NonNullable, 5);
77
    ///
78
    /// // Populate the values in reverse order.
79
    /// let mut range = builder.uninit_range(5);
80
    /// for i in [4, 3, 2, 1, 0] {
81
    ///     range[i] = MaybeUninit::new(i as i32);
82
    /// }
83
    /// range.finish();
84
    ///
85
    /// let built = builder.finish_into_primitive();
86
    ///
87
    /// assert_eq!(built.as_slice::<i32>(), &[0i32, 1, 2, 3, 4]);
88
    /// ```
UNCOV
89
    pub fn uninit_range(&mut self, len: usize) -> UninitRange<'_, T> {
×
UNCOV
90
        let offset = self.values.len();
×
UNCOV
91
        assert!(
×
UNCOV
92
            offset + len <= self.values.capacity(),
×
93
            "uninit_range of len {len} exceeds builder capacity {}",
×
94
            self.values.capacity()
×
95
        );
96

UNCOV
97
        UninitRange {
×
UNCOV
98
            offset,
×
UNCOV
99
            len,
×
UNCOV
100
            builder: self,
×
UNCOV
101
        }
×
UNCOV
102
    }
×
103

104
    pub fn finish_into_primitive(&mut self) -> PrimitiveArray {
56✔
105
        let validity = self
56✔
106
            .nulls
56✔
107
            .finish_with_nullability(self.dtype().nullability());
56✔
108

109
        PrimitiveArray::new(std::mem::take(&mut self.values).freeze(), validity)
56✔
110
    }
56✔
111

112
    pub fn extend_with_iterator(&mut self, iter: impl IntoIterator<Item = T>, mask: Mask) {
×
113
        self.values.extend(iter);
×
114
        self.extend_with_validity_mask(mask)
×
115
    }
×
116

117
    fn extend_with_validity_mask(&mut self, validity_mask: Mask) {
172✔
118
        self.nulls.append_validity_mask(validity_mask);
172✔
119
    }
172✔
120
}
121

122
impl<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 {
72✔
128
        self
72✔
129
    }
72✔
130

131
    fn dtype(&self) -> &DType {
320✔
132
        &self.dtype
320✔
133
    }
320✔
134

135
    fn len(&self) -> usize {
384✔
136
        self.values.len()
384✔
137
    }
384✔
138

UNCOV
139
    fn append_zeros(&mut self, n: usize) {
×
UNCOV
140
        self.values.push_n(T::default(), n);
×
UNCOV
141
        self.nulls.append_n_non_nulls(n);
×
UNCOV
142
    }
×
143

144
    fn append_nulls(&mut self, n: usize) {
×
145
        self.values.push_n(T::default(), n);
×
146
        self.nulls.append_n_nulls(n);
×
147
    }
×
148

149
    fn extend_from_array(&mut self, array: &dyn Array) -> VortexResult<()> {
172✔
150
        let array = array.to_primitive()?;
172✔
151
        if array.ptype() != T::PTYPE {
172✔
152
            vortex_bail!("Cannot extend from array with different ptype");
×
153
        }
172✔
154

155
        self.values.extend_from_slice(array.as_slice::<T>());
172✔
156

157
        self.extend_with_validity_mask(array.validity_mask()?);
172✔
158

159
        Ok(())
172✔
160
    }
172✔
161

UNCOV
162
    fn ensure_capacity(&mut self, capacity: usize) {
×
UNCOV
163
        if capacity > self.values.capacity() {
×
UNCOV
164
            self.values.reserve(capacity - self.values.len());
×
UNCOV
165
            self.nulls.ensure_capacity(capacity);
×
UNCOV
166
        }
×
UNCOV
167
    }
×
168

UNCOV
169
    fn set_validity(&mut self, validity: Mask) {
×
UNCOV
170
        self.nulls = LazyNullBufferBuilder::new(validity.len());
×
UNCOV
171
        self.nulls.append_validity_mask(validity);
×
UNCOV
172
    }
×
173

174
    fn finish(&mut self) -> ArrayRef {
56✔
175
        self.finish_into_primitive().into_array()
56✔
176
    }
56✔
177
}
178

179
pub struct UninitRange<'a, T> {
180
    offset: usize,
181
    len: usize,
182
    builder: &'a mut PrimitiveBuilder<T>,
183
}
184

185
impl<T> Deref for UninitRange<'_, T> {
186
    type Target = [MaybeUninit<T>];
187

UNCOV
188
    fn deref(&self) -> &[MaybeUninit<T>] {
×
UNCOV
189
        let start = self.builder.values.as_ptr();
×
190
        unsafe {
191
            // SAFETY: start + len is checked on construction to be in range.
UNCOV
192
            let dst = std::slice::from_raw_parts(start, self.len);
×
193

194
            // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
UNCOV
195
            let dst: &[MaybeUninit<T>] = std::mem::transmute(dst);
×
196

UNCOV
197
            dst
×
198
        }
UNCOV
199
    }
×
200
}
201

202
impl<T> DerefMut for UninitRange<'_, T> {
UNCOV
203
    fn deref_mut(&mut self) -> &mut [MaybeUninit<T>] {
×
UNCOV
204
        &mut self.builder.values.spare_capacity_mut()[..self.len]
×
UNCOV
205
    }
×
206
}
207

208
impl<T> UninitRange<'_, T> {
209
    /// Set a validity bit at the given index. The index is relative to the start of this range
210
    /// of the builder.
211
    pub fn set_bit(&mut self, index: usize, v: bool) {
×
212
        self.builder.nulls.set_bit(self.offset + index, v);
×
213
    }
×
214

215
    /// Set values from an initialized range.
UNCOV
216
    pub fn copy_from_init(&mut self, offset: usize, len: usize, src: &[T])
×
UNCOV
217
    where
×
UNCOV
218
        T: Copy,
×
219
    {
220
        // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
UNCOV
221
        let uninit_src: &[MaybeUninit<T>] = unsafe { std::mem::transmute(src) };
×
222

UNCOV
223
        let dst = &mut self[offset..][..len];
×
UNCOV
224
        dst.copy_from_slice(uninit_src);
×
UNCOV
225
    }
×
226

227
    /// Finish building this range, marking it as initialized and advancing the length of the
228
    /// underlying values buffer.
UNCOV
229
    pub fn finish(self) {
×
230
        // SAFETY: constructor enforces that offset + len does not exceed the capacity of the array.
UNCOV
231
        unsafe { self.builder.values.set_len(self.offset + self.len) };
×
UNCOV
232
    }
×
233
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc