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

vortex-data / vortex / 16331938722

16 Jul 2025 10:49PM UTC coverage: 80.702% (-0.9%) from 81.557%
16331938722

push

github

web-flow
feat: build with stable rust (#3881)

120 of 173 new or added lines in 28 files covered. (69.36%)

174 existing lines in 102 files now uncovered.

41861 of 51871 relevant lines covered (80.7%)

157487.71 hits per line

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

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

4
//! Builders for Vortex arrays.
5
//!
6
//! Every logical type in Vortex has a canonical (uncompressed) in-memory encoding. This module
7
//! provides pre-allocated builders to construct new canonical arrays.
8
//!
9
//! ## Example:
10
//!
11
//! ```
12
//! use vortex_array::builders::{builder_with_capacity, ArrayBuilderExt};
13
//! use vortex_dtype::{DType, Nullability};
14
//!
15
//! // Create a new builder for string data.
16
//! let mut builder = builder_with_capacity(&DType::Utf8(Nullability::NonNullable), 4);
17
//!
18
//! builder.append_scalar(&"a".into()).unwrap();
19
//! builder.append_scalar(&"b".into()).unwrap();
20
//! builder.append_scalar(&"c".into()).unwrap();
21
//! builder.append_scalar(&"d".into()).unwrap();
22
//!
23
//! let strings = builder.finish();
24
//!
25
//! assert_eq!(strings.scalar_at(0).unwrap(), "a".into());
26
//! assert_eq!(strings.scalar_at(1).unwrap(), "b".into());
27
//! assert_eq!(strings.scalar_at(2).unwrap(), "c".into());
28
//! assert_eq!(strings.scalar_at(3).unwrap(), "d".into());
29
//! ```
30

31
mod bool;
32
mod decimal;
33
mod extension;
34
mod lazy_validity_builder;
35
mod list;
36
mod null;
37
mod primitive;
38
mod struct_;
39
mod varbinview;
40

41
use std::any::Any;
42

43
pub use bool::*;
44
pub use decimal::*;
45
pub use extension::*;
46
pub use list::*;
47
pub use null::*;
48
pub use primitive::*;
49
pub use struct_::*;
50
pub use varbinview::*;
51
use vortex_dtype::{DType, match_each_native_ptype};
52
use vortex_error::{VortexResult, vortex_bail, vortex_err};
53
use vortex_mask::Mask;
54
use vortex_scalar::{
55
    BinaryScalar, BoolScalar, DecimalValue, ExtScalar, ListScalar, PrimitiveScalar, Scalar,
56
    ScalarValue, StructScalar, Utf8Scalar, match_each_decimal_value, match_each_decimal_value_type,
57
};
58

59
use crate::arrays::smallest_storage_type;
60
use crate::{Array, ArrayRef};
61

62
pub trait ArrayBuilder: Send {
63
    fn as_any(&self) -> &dyn Any;
64

65
    fn as_any_mut(&mut self) -> &mut dyn Any;
66

67
    fn dtype(&self) -> &DType;
68

69
    fn len(&self) -> usize;
70

71
    fn is_empty(&self) -> bool {
×
72
        self.len() == 0
×
73
    }
×
74

75
    /// Append a "zero" value to the array.
76
    fn append_zero(&mut self) {
253✔
77
        self.append_zeros(1)
253✔
78
    }
253✔
79

80
    /// Appends n "zero" values to the array.
81
    fn append_zeros(&mut self, n: usize);
82

83
    /// Append a "null" value to the array.
84
    fn append_null(&mut self) {
315✔
85
        self.append_nulls(1)
315✔
86
    }
315✔
87

88
    /// Appends n "null" values to the array.
89
    fn append_nulls(&mut self, n: usize);
90

91
    /// Extends the array with the provided array, canonicalizing if necessary.
92
    fn extend_from_array(&mut self, array: &dyn Array) -> VortexResult<()>;
93

94
    /// Ensure that the builder can hold at least `capacity` number of items
95
    fn ensure_capacity(&mut self, capacity: usize);
96

97
    /// Override builders validity with the one provided
98
    fn set_validity(&mut self, validity: Mask);
99

100
    /// Constructs an Array from the builder components.
101
    ///
102
    /// # Panics
103
    ///
104
    /// This function may panic if the builder's methods are called with invalid arguments. If only
105
    /// the methods on this interface are used, the builder should not panic. However, specific
106
    /// builders have interfaces that may be misused. For example, if the number of values in a
107
    /// [PrimitiveBuilder]'s [vortex_buffer::BufferMut] does not match the number of validity bits,
108
    /// the PrimitiveBuilder's [Self::finish] will panic.
109
    fn finish(&mut self) -> ArrayRef;
110
}
111

112
/// Construct a new canonical builder for the given [`DType`].
113
///
114
///
115
/// # Example
116
///
117
/// ```
118
/// use vortex_array::builders::{builder_with_capacity, ArrayBuilderExt};
119
/// use vortex_dtype::{DType, Nullability};
120
///
121
/// // Create a new builder for string data.
122
/// let mut builder = builder_with_capacity(&DType::Utf8(Nullability::NonNullable), 4);
123
///
124
/// builder.append_scalar(&"a".into()).unwrap();
125
/// builder.append_scalar(&"b".into()).unwrap();
126
/// builder.append_scalar(&"c".into()).unwrap();
127
/// builder.append_scalar(&"d".into()).unwrap();
128
///
129
/// let strings = builder.finish();
130
///
131
/// assert_eq!(strings.scalar_at(0).unwrap(), "a".into());
132
/// assert_eq!(strings.scalar_at(1).unwrap(), "b".into());
133
/// assert_eq!(strings.scalar_at(2).unwrap(), "c".into());
134
/// assert_eq!(strings.scalar_at(3).unwrap(), "d".into());
135
/// ```
136
pub fn builder_with_capacity(dtype: &DType, capacity: usize) -> Box<dyn ArrayBuilder> {
22,585✔
137
    match dtype {
22,585✔
138
        DType::Null => Box::new(NullBuilder::new()),
×
139
        DType::Bool(n) => Box::new(BoolBuilder::with_capacity(*n, capacity)),
372✔
140
        DType::Primitive(ptype, n) => {
16,545✔
141
            match_each_native_ptype!(ptype, |P| {
16,545✔
142
                Box::new(PrimitiveBuilder::<P>::with_capacity(*n, capacity))
168✔
143
            })
144
        }
145
        DType::Decimal(decimal_type, n) => {
886✔
146
            match_each_decimal_value_type!(smallest_storage_type(decimal_type), |D| {
886✔
147
                Box::new(DecimalBuilder::with_capacity::<D>(
144✔
148
                    capacity,
144✔
149
                    *decimal_type,
144✔
150
                    *n,
144✔
151
                ))
144✔
152
            })
153
        }
154
        DType::Utf8(n) => Box::new(VarBinViewBuilder::with_capacity(DType::Utf8(*n), capacity)),
4,260✔
155
        DType::Binary(n) => Box::new(VarBinViewBuilder::with_capacity(
108✔
156
            DType::Binary(*n),
108✔
157
            capacity,
108✔
158
        )),
108✔
159
        DType::Struct(struct_dtype, n) => Box::new(StructBuilder::with_capacity(
217✔
160
            struct_dtype.clone(),
217✔
161
            *n,
217✔
162
            capacity,
217✔
163
        )),
217✔
164
        DType::List(dtype, n) => Box::new(ListBuilder::<u64>::with_capacity(
145✔
165
            dtype.clone(),
145✔
166
            *n,
145✔
167
            capacity,
145✔
168
        )),
145✔
169
        DType::Extension(ext_dtype) => {
52✔
170
            Box::new(ExtensionBuilder::with_capacity(ext_dtype.clone(), capacity))
52✔
171
        }
172
    }
173
}
22,585✔
174

175
pub trait ArrayBuilderExt: ArrayBuilder {
176
    /// A generic function to append a scalar value to the builder.
177
    fn append_scalar_value(&mut self, value: ScalarValue) -> VortexResult<()> {
19,823✔
178
        if value.is_null() {
19,823✔
179
            self.append_null();
×
180
            Ok(())
×
181
        } else {
182
            self.append_scalar(&Scalar::new(self.dtype().clone(), value))
19,823✔
183
        }
184
    }
19,823✔
185

186
    /// A generic function to append a scalar to the builder.
187
    fn append_scalar(&mut self, scalar: &Scalar) -> VortexResult<()> {
32,368✔
188
        if scalar.dtype() != self.dtype() {
32,368✔
189
            vortex_bail!(
×
190
                "Builder has dtype {:?}, scalar has {:?}",
×
191
                self.dtype(),
×
192
                scalar.dtype()
×
193
            )
194
        }
32,368✔
195
        match scalar.dtype() {
32,368✔
196
            DType::Null => self
×
197
                .as_any_mut()
×
198
                .downcast_mut::<NullBuilder>()
×
199
                .ok_or_else(|| vortex_err!("Cannot append null scalar to non-null builder"))?
×
200
                .append_null(),
×
201
            DType::Bool(_) => self
288✔
202
                .as_any_mut()
288✔
203
                .downcast_mut::<BoolBuilder>()
288✔
204
                .ok_or_else(|| vortex_err!("Cannot append bool scalar to non-bool builder"))?
288✔
205
                .append_option(BoolScalar::try_from(scalar)?.value()),
288✔
206
            DType::Primitive(ptype, ..) => {
23,425✔
207
                match_each_native_ptype!(ptype, |P| {
23,425✔
208
                    self.as_any_mut()
9✔
209
                        .downcast_mut::<PrimitiveBuilder<P>>()
9✔
210
                        .ok_or_else(|| {
9✔
211
                            vortex_err!("Cannot append primitive scalar to non-primitive builder")
×
UNCOV
212
                        })?
×
213
                        .append_option(PrimitiveScalar::try_from(scalar)?.typed_value::<P>())
9✔
214
                })
215
            }
216
            DType::Decimal(..) => {
217
                let builder = self
2,096✔
218
                    .as_any_mut()
2,096✔
219
                    .downcast_mut::<DecimalBuilder>()
2,096✔
220
                    .ok_or_else(|| {
2,096✔
221
                        vortex_err!("Cannot append decimal scalar to non-decimal builder")
×
UNCOV
222
                    })?;
×
223
                match scalar.as_decimal().decimal_value() {
2,096✔
224
                    None => builder.append_null(),
×
225
                    Some(v) => match_each_decimal_value!(v, |dec_val| {
2,096✔
226
                        builder.append_value(*dec_val);
144✔
227
                    }),
144✔
228
                }
229
            }
230
            DType::Utf8(_) => self
5,423✔
231
                .as_any_mut()
5,423✔
232
                .downcast_mut::<VarBinViewBuilder>()
5,423✔
233
                .ok_or_else(|| vortex_err!("Cannot append utf8 scalar to non-utf8 builder"))?
5,423✔
234
                .append_option(Utf8Scalar::try_from(scalar)?.value()),
5,423✔
235
            DType::Binary(_) => self
144✔
236
                .as_any_mut()
144✔
237
                .downcast_mut::<VarBinViewBuilder>()
144✔
238
                .ok_or_else(|| vortex_err!("Cannot append binary scalar to non-binary builder"))?
144✔
239
                .append_option(BinaryScalar::try_from(scalar)?.value()),
144✔
240
            DType::Struct(..) => self
×
241
                .as_any_mut()
×
242
                .downcast_mut::<StructBuilder>()
×
243
                .ok_or_else(|| vortex_err!("Cannot append struct scalar to non-struct builder"))?
×
244
                .append_value(StructScalar::try_from(scalar)?)?,
×
245
            DType::List(..) => self
×
246
                .as_any_mut()
×
247
                .downcast_mut::<ListBuilder<u64>>()
×
248
                .ok_or_else(|| vortex_err!("Cannot append list scalar to non-list builder"))?
×
249
                .append_value(ListScalar::try_from(scalar)?)?,
×
250
            DType::Extension(..) => self
992✔
251
                .as_any_mut()
992✔
252
                .downcast_mut::<ExtensionBuilder>()
992✔
253
                .ok_or_else(|| {
992✔
254
                    vortex_err!("Cannot append extension scalar to non-extension builder")
×
UNCOV
255
                })?
×
256
                .append_value(ExtScalar::try_from(scalar)?)?,
992✔
257
        }
258
        Ok(())
32,368✔
259
    }
32,368✔
260
}
261

262
impl<T: ?Sized + ArrayBuilder> ArrayBuilderExt for T {}
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