vortex_vector/primitive/
generic.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Definition and implementation of [`PVector<T>`].
5
6use std::fmt::Debug;
7use std::ops::BitAnd;
8use std::ops::RangeBounds;
9
10use vortex_buffer::Buffer;
11use vortex_dtype::NativePType;
12use vortex_error::VortexExpect;
13use vortex_error::VortexResult;
14use vortex_error::vortex_ensure;
15use vortex_mask::Mask;
16
17use crate::VectorOps;
18use crate::primitive::PScalar;
19use crate::primitive::PVectorMut;
20
21/// An immutable vector of generic primitive values.
22///
23/// `T` is expected to be bound by [`NativePType`], which templates an internal [`Buffer<T>`] that
24/// stores the elements of the vector.
25#[derive(Default, Debug, Clone)]
26pub struct PVector<T> {
27    /// The buffer representing the vector elements.
28    pub(super) elements: Buffer<T>,
29    /// The validity mask (where `true` represents an element is **not** null).
30    pub(super) validity: Mask,
31}
32
33impl<T> PVector<T> {
34    /// Creates a new [`PVector<T>`] from the given elements buffer and validity mask.
35    ///
36    /// # Panics
37    ///
38    /// Panics if the length of the validity mask does not match the length of the elements buffer.
39    pub fn new(elements: Buffer<T>, validity: Mask) -> Self {
40        Self::try_new(elements, validity).vortex_expect("Failed to create `PVector`")
41    }
42
43    /// Tries to create a new [`PVector<T>`] from the given elements buffer and validity mask.
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if the length of the validity mask does not match the length of the
48    /// elements buffer.
49    pub fn try_new(elements: Buffer<T>, validity: Mask) -> VortexResult<Self> {
50        vortex_ensure!(
51            validity.len() == elements.len(),
52            "`PVector` validity mask must have the same length as elements"
53        );
54
55        Ok(Self { elements, validity })
56    }
57
58    /// Creates a new [`PVector<T>`] from the given elements buffer and validity mask without
59    /// validation.
60    ///
61    /// # Safety
62    ///
63    /// The caller must ensure that the validity mask has the same length as the elements buffer.
64    pub unsafe fn new_unchecked(elements: Buffer<T>, validity: Mask) -> Self {
65        if cfg!(debug_assertions) {
66            Self::new(elements, validity)
67        } else {
68            Self { elements, validity }
69        }
70    }
71
72    /// Decomposes the primitive vector into its constituent parts (buffer and validity).
73    pub fn into_parts(self) -> (Buffer<T>, Mask) {
74        (self.elements, self.validity)
75    }
76
77    /// Decomposes the primitive vector into its constituent parts by mutable reference.
78    ///
79    /// # Safety
80    ///
81    /// The caller must ensure that no other references to the internal parts exist while mutable
82    pub unsafe fn as_parts_mut(&mut self) -> (&mut Buffer<T>, &mut Mask) {
83        (&mut self.elements, &mut self.validity)
84    }
85
86    /// Gets a nullable element at the given index, panicking on out-of-bounds.
87    ///
88    /// If the element at the given index is null, returns `None`. Otherwise, returns `Some(x)`,
89    /// where `x: T`.
90    ///
91    /// Note that this `get` method is different from the standard library [`slice::get`], which
92    /// returns `None` if the index is out of bounds. This method will panic if the index is out of
93    /// bounds, and return `None` if the elements is null.
94    ///
95    /// # Panics
96    ///
97    /// Panics if the index is out of bounds.
98    pub fn get(&self, index: usize) -> Option<&T> {
99        self.validity.value(index).then(|| &self.elements[index])
100    }
101
102    /// Returns the internal [`Buffer`] of the [`PVector`].
103    ///
104    /// Note that the internal buffer may hold garbage data in place of nulls. That information is
105    /// tracked by the [`validity()`](Self::validity).
106    #[inline]
107    pub fn elements(&self) -> &Buffer<T> {
108        &self.elements
109    }
110}
111
112impl<T: NativePType> AsRef<[T]> for PVector<T> {
113    /// Returns an immutable slice over the internal buffer with elements of type `T`.
114    ///
115    /// Note that this slice may contain garbage data where the [`validity()`] mask states that an
116    /// element is invalid.
117    ///
118    /// The caller should check the [`validity()`] before performing any operations.
119    ///
120    /// [`validity()`]: crate::VectorOps::validity
121    #[inline]
122    fn as_ref(&self) -> &[T] {
123        self.elements.as_slice()
124    }
125}
126
127impl<T: NativePType> VectorOps for PVector<T> {
128    type Mutable = PVectorMut<T>;
129    type Scalar = PScalar<T>;
130
131    fn len(&self) -> usize {
132        self.elements.len()
133    }
134
135    fn validity(&self) -> &Mask {
136        &self.validity
137    }
138
139    fn mask_validity(&mut self, mask: &Mask) {
140        self.validity = self.validity.bitand(mask);
141    }
142
143    fn scalar_at(&self, index: usize) -> PScalar<T> {
144        assert!(index < self.len(), "Index out of bounds in `PVector`");
145        PScalar::<T>::new(self.validity.value(index).then(|| self.elements[index]))
146    }
147
148    fn slice(&self, range: impl RangeBounds<usize> + Clone + Debug) -> Self {
149        let elements = self.elements.slice(range.clone());
150        let validity = self.validity.slice(range);
151        Self::new(elements, validity)
152    }
153
154    fn clear(&mut self) {
155        self.elements.clear();
156        self.validity.clear();
157    }
158
159    /// Try to convert self into a mutable vector.
160    fn try_into_mut(self) -> Result<PVectorMut<T>, Self> {
161        let elements = match self.elements.try_into_mut() {
162            Ok(elements) => elements,
163            Err(elements) => {
164                return Err(Self {
165                    elements,
166                    validity: self.validity,
167                });
168            }
169        };
170
171        match self.validity.try_into_mut() {
172            Ok(validity_mut) => Ok(PVectorMut {
173                elements,
174                validity: validity_mut,
175            }),
176            Err(validity) => Err(Self {
177                elements: elements.freeze(),
178                validity,
179            }),
180        }
181    }
182
183    fn into_mut(self) -> PVectorMut<T> {
184        let elements = self.elements.into_mut();
185        let validity = self.validity.into_mut();
186
187        PVectorMut { elements, validity }
188    }
189}