Skip to content

Commit 4d86b96

Browse files
committed
add missing methods to decimal vectors
Adds `with_capacity` and other constructors for the mutable decimal vectors, and additionally moves more things around. I also removed the get method since it now returns a reference since you can just call `.as_ref()` and call the native `slice::get` method. Signed-off-by: Connor Tsui <[email protected]>
1 parent bea1b59 commit 4d86b96

File tree

9 files changed

+304
-25
lines changed

9 files changed

+304
-25
lines changed

vortex-vector/src/decimal/generic.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Definition and implementation of [`DVector<D>`].
5+
46
use vortex_buffer::Buffer;
57
use vortex_dtype::{NativeDecimalType, PrecisionScale};
68
use vortex_error::{VortexExpect, VortexResult, vortex_bail};
79
use vortex_mask::Mask;
810

911
use crate::{DVectorMut, VectorOps};
1012

11-
/// A specifically typed decimal vector.
13+
/// An immutable vector of generic decimal values.
14+
///
15+
/// `DVector<D>` can be considered a borrowed / frozen version of [`DVectorMut<D>`], which is
16+
/// created via the [`freeze`](crate::VectorMutOps::freeze) method.
17+
///
18+
/// See the documentation for [`DVectorMut<D>`] for more information.
1219
#[derive(Debug, Clone)]
1320
pub struct DVector<D> {
21+
/// The precision and scale of each decimal in the decimal vector.
1422
pub(super) ps: PrecisionScale<D>,
23+
/// The buffer representing the vector decimal elements.
1524
pub(super) elements: Buffer<D>,
25+
/// The validity mask (where `true` represents an element is **not** null).
1626
pub(super) validity: Mask,
1727
}
1828

1929
impl<D: NativeDecimalType> DVector<D> {
20-
/// Try to create a new decimal vector from the given elements and validity.
30+
/// Creates a new [`DVector<D>`] from the given [`PrecisionScale`], elements buffer, and
31+
/// validity mask.
2132
///
2233
/// # Panics
2334
///
@@ -29,7 +40,8 @@ impl<D: NativeDecimalType> DVector<D> {
2940
Self::try_new(ps, elements, validity).vortex_expect("Failed to create `DVector`")
3041
}
3142

32-
/// Try to create a new decimal vector from the given elements and validity.
43+
/// Tries to create a new [`DVector<D>`] from the given [`PrecisionScale`], elements buffer, and
44+
/// validity mask.
3345
///
3446
/// # Errors
3547
///
@@ -66,7 +78,8 @@ impl<D: NativeDecimalType> DVector<D> {
6678
})
6779
}
6880

69-
/// Create a new decimal vector from the given elements and validity without validation.
81+
/// Creates a new [`DVector<D>`] from the given [`PrecisionScale`], elements buffer, and
82+
/// validity mask, _without_ validation.
7083
///
7184
/// # Safety
7285
///
@@ -100,6 +113,33 @@ impl<D: NativeDecimalType> DVector<D> {
100113
pub fn precision_scale(&self) -> PrecisionScale<D> {
101114
self.ps
102115
}
116+
117+
/// Returns a reference to the underlying elements buffer containing the decimal data.
118+
pub fn elements(&self) -> &Buffer<D> {
119+
&self.elements
120+
}
121+
122+
/// Gets a nullable element at the given index, **WITHOUT** bounds checking.
123+
///
124+
/// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
125+
/// where `x: D`.
126+
///
127+
/// Note that this `get` method is different from the standard library [`slice::get`], which
128+
/// returns `None` if the index is out of bounds. This method will panic if the index is out of
129+
/// bounds, and return `None` if the elements is null.
130+
///
131+
/// # Panics
132+
///
133+
/// Panics if the index is out of bounds.
134+
pub fn get(&self, index: usize) -> Option<&D> {
135+
self.validity.value(index).then(|| &self.elements[index])
136+
}
137+
}
138+
139+
impl<D: NativeDecimalType> AsRef<[D]> for DVector<D> {
140+
fn as_ref(&self) -> &[D] {
141+
&self.elements
142+
}
103143
}
104144

105145
impl<D: NativeDecimalType> VectorOps for DVector<D> {

vortex-vector/src/decimal/generic_mut.rs

Lines changed: 126 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,151 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Definition and implementation of [`DVectorMut<D>`].
5+
46
use vortex_buffer::BufferMut;
5-
use vortex_dtype::{NativeDecimalType, PrecisionScale};
6-
use vortex_error::{VortexResult, vortex_bail};
7+
use vortex_dtype::{DecimalDType, NativeDecimalType, PrecisionScale};
8+
use vortex_error::{VortexExpect, VortexResult, vortex_bail};
79
use vortex_mask::MaskMut;
810

911
use crate::{DVector, VectorMutOps, VectorOps};
1012

1113
/// A specifically typed mutable decimal vector.
1214
#[derive(Debug, Clone)]
1315
pub struct DVectorMut<D> {
16+
/// The precision and scale of each decimal in the decimal vector.
1417
pub(super) ps: PrecisionScale<D>,
18+
/// The mutable buffer representing the vector decimal elements.
1519
pub(super) elements: BufferMut<D>,
20+
/// The validity mask (where `true` represents an element is **not** null).
1621
pub(super) validity: MaskMut,
1722
}
1823

1924
impl<D: NativeDecimalType> DVectorMut<D> {
25+
/// Creates a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer, and
26+
/// validity mask.
27+
///
28+
/// # Panics
29+
///
30+
/// Panics if:
31+
///
32+
/// - The lengths of the `elements` and `validity` do not match.
33+
/// - Any of the elements are out of bounds for the given [`PrecisionScale`].
34+
pub fn new(ps: PrecisionScale<D>, elements: BufferMut<D>, validity: MaskMut) -> Self {
35+
Self::try_new(ps, elements, validity).vortex_expect("Failed to create `DVector`")
36+
}
37+
38+
/// Tries to create a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer,
39+
/// and validity mask.
40+
///
41+
/// # Errors
42+
///
43+
/// Returns an error if:
44+
///
45+
/// - The lengths of the `elements` and `validity` do not match.
46+
/// - Any of the elements are out of bounds for the given [`PrecisionScale`].
47+
pub fn try_new(
48+
ps: PrecisionScale<D>,
49+
elements: BufferMut<D>,
50+
validity: MaskMut,
51+
) -> VortexResult<Self> {
52+
if elements.len() != validity.len() {
53+
vortex_bail!(
54+
"Elements length {} does not match validity length {}",
55+
elements.len(),
56+
validity.len()
57+
);
58+
}
59+
60+
// We assert that each element is within bounds for the given precision/scale.
61+
if !elements.iter().all(|e| ps.is_valid(*e)) {
62+
vortex_bail!(
63+
"One or more elements are out of bounds for precision {} and scale {}",
64+
ps.precision(),
65+
ps.scale()
66+
);
67+
}
68+
69+
Ok(Self {
70+
ps,
71+
elements,
72+
validity,
73+
})
74+
}
75+
76+
/// Creates a new [`DVectorMut<D>`] from the given [`PrecisionScale`], elements buffer, and
77+
/// validity mask, _without_ validation.
78+
///
79+
/// # Safety
80+
///
81+
/// The caller must ensure:
82+
///
83+
/// - The lengths of the elements and validity are equal.
84+
/// - All elements are in bounds for the given [`PrecisionScale`].
85+
pub unsafe fn new_unchecked(
86+
ps: PrecisionScale<D>,
87+
elements: BufferMut<D>,
88+
validity: MaskMut,
89+
) -> Self {
90+
if cfg!(debug_assertions) {
91+
Self::try_new(ps, elements, validity).vortex_expect("Failed to create `DVectorMut`")
92+
} else {
93+
Self {
94+
ps,
95+
elements,
96+
validity,
97+
}
98+
}
99+
}
100+
101+
/// Create a new mutable primitive vector with the given capacity.
102+
pub fn with_capacity(decimal_dtype: &DecimalDType, capacity: usize) -> Self {
103+
Self {
104+
ps: PrecisionScale::try_from(decimal_dtype)
105+
.vortex_expect("TODO(someone): This definitely should not be fallible"),
106+
elements: BufferMut::with_capacity(capacity),
107+
validity: MaskMut::with_capacity(capacity),
108+
}
109+
}
110+
111+
/// Decomposes the decimal vector into its constituent parts ([`PrecisionScale`], decimal
112+
/// buffer, and validity).
113+
pub fn into_parts(self) -> (PrecisionScale<D>, BufferMut<D>, MaskMut) {
114+
(self.ps, self.elements, self.validity)
115+
}
116+
20117
/// Get the precision/scale of the decimal vector.
21118
pub fn precision_scale(&self) -> PrecisionScale<D> {
22119
self.ps
23120
}
24121

25-
/// Get a nullable element at the given index.
122+
/// Returns a reference to the underlying elements buffer containing the decimal data.
123+
pub fn elements(&self) -> &BufferMut<D> {
124+
&self.elements
125+
}
126+
127+
/// Returns a mutable reference to the underlying elements buffer containing the decimal data.
128+
///
129+
/// # Safety
130+
///
131+
/// Modifying the elements buffer directly may violate the precision/scale constraints.
132+
/// The caller must ensure that any modifications maintain these invariants.
133+
pub unsafe fn elements_mut(&mut self) -> &mut BufferMut<D> {
134+
&mut self.elements
135+
}
136+
137+
/// Gets a nullable element at the given index, **WITHOUT** bounds checking.
138+
///
139+
/// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
140+
/// where `x: D`.
141+
///
142+
/// Note that this `get` method is different from the standard library [`slice::get`], which
143+
/// returns `None` if the index is out of bounds. This method will panic if the index is out of
144+
/// bounds, and return `None` if the elements is null.
145+
///
146+
/// # Panics
147+
///
148+
/// Panics if the index is out of bounds.
26149
pub fn get(&self, index: usize) -> Option<&D> {
27150
self.validity.value(index).then(|| &self.elements[index])
28151
}
@@ -41,16 +164,6 @@ impl<D: NativeDecimalType> DVectorMut<D> {
41164
self.validity.append_n(true, 1);
42165
Ok(())
43166
}
44-
45-
/// Returns a mutable reference to the underlying elements buffer.
46-
///
47-
/// # Safety
48-
///
49-
/// Modifying the elements buffer directly may violate the precision/scale constraints.
50-
/// The caller must ensure that any modifications maintain these invariants.
51-
pub unsafe fn elements_mut(&mut self) -> &mut [D] {
52-
&mut self.elements
53-
}
54167
}
55168

56169
impl<D: NativeDecimalType> AsRef<[D]> for DVectorMut<D> {

vortex-vector/src/decimal/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Definitions and implementations of decimal vector types.
5+
//!
6+
//! The types that hold data are [`DVector`] and [`DVectorMut`], which are generic over types `D`
7+
//! that implement [`NativeDecimalType`].
8+
//!
9+
//! [`DecimalVector`] and [`DecimalVectorMut`] are enums that wrap all of the different possible
10+
//! [`DVector`]s. There are several macros defined in this crate to make working with these
11+
//! primitive vector types easier.
12+
413
mod generic;
514
pub use generic::DVector;
615

vortex-vector/src/decimal/vector.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Definition and implementation of [`DecimalVector`].
5+
46
use vortex_dtype::{DecimalTypeDowncast, DecimalTypeUpcast, NativeDecimalType, i256};
57
use vortex_error::vortex_panic;
68
use vortex_mask::Mask;

vortex-vector/src/decimal/vector_mut.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4-
use vortex_dtype::{DecimalTypeDowncast, DecimalTypeUpcast, NativeDecimalType, i256};
4+
//! Definition and implementation of [`DecimalVectorMut`].
5+
6+
use vortex_dtype::{
7+
DecimalDType, DecimalType, DecimalTypeDowncast, DecimalTypeUpcast, NativeDecimalType, i256,
8+
};
59
use vortex_error::vortex_panic;
610

711
use crate::decimal::DVectorMut;
@@ -24,6 +28,34 @@ pub enum DecimalVectorMut {
2428
D256(DVectorMut<i256>),
2529
}
2630

31+
impl DecimalVectorMut {
32+
/// Create a new mutable decimal vector with the given primitive type and capacity.
33+
pub fn with_capacity(decimal_dtype: &DecimalDType, capacity: usize) -> Self {
34+
let decimal_kind = DecimalType::smallest_decimal_value_type(decimal_dtype);
35+
36+
match decimal_kind {
37+
DecimalType::I8 => {
38+
DecimalVectorMut::D8(DVectorMut::<i8>::with_capacity(decimal_dtype, capacity))
39+
}
40+
DecimalType::I16 => {
41+
DecimalVectorMut::D16(DVectorMut::<i16>::with_capacity(decimal_dtype, capacity))
42+
}
43+
DecimalType::I32 => {
44+
DecimalVectorMut::D32(DVectorMut::<i32>::with_capacity(decimal_dtype, capacity))
45+
}
46+
DecimalType::I64 => {
47+
DecimalVectorMut::D64(DVectorMut::<i64>::with_capacity(decimal_dtype, capacity))
48+
}
49+
DecimalType::I128 => {
50+
DecimalVectorMut::D128(DVectorMut::<i128>::with_capacity(decimal_dtype, capacity))
51+
}
52+
DecimalType::I256 => {
53+
DecimalVectorMut::D256(DVectorMut::<i256>::with_capacity(decimal_dtype, capacity))
54+
}
55+
}
56+
}
57+
}
58+
2759
impl VectorMutOps for DecimalVectorMut {
2860
type Immutable = DecimalVector;
2961

vortex-vector/src/primitive/generic.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,15 @@ impl<T> PVector<T> {
7171
(self.elements, self.validity)
7272
}
7373

74-
/// Gets a nullable element at the given index.
74+
/// Gets a nullable element at the given index, **WITHOUT** bounds checking.
7575
///
7676
/// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
7777
/// where `x: T`.
7878
///
79+
/// Note that this `get` method is different from the standard library [`slice::get`], which
80+
/// returns `None` if the index is out of bounds. This method will panic if the index is out of
81+
/// bounds, and return `None` if the elements is null.
82+
///
7983
/// # Panics
8084
///
8185
/// Panics if the index is out of bounds.

vortex-vector/src/primitive/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
//! [`PVector`]s. There are several macros defined in this crate to make working with these
1212
//! primitive vector types easier.
1313
//!
14-
//! [`NativePType`]: vortex_dtype::NativePType
1514
//! [`f16`]: vortex_dtype::half::f16
1615
1716
mod generic;

vortex-vector/src/primitive/vector_mut.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ impl PrimitiveVectorMut {
6060
PrimitiveVectorMut::F64(_) => PType::F64,
6161
}
6262
}
63-
}
6463

65-
impl PrimitiveVectorMut {
6664
/// Create a new mutable primitive vector with the given primitive type and capacity.
6765
pub fn with_capacity(ptype: PType, capacity: usize) -> Self {
6866
match ptype {

0 commit comments

Comments
 (0)