vortex_vector/
scalar.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_dtype::DType;
5use vortex_error::vortex_panic;
6
7use crate::ScalarOps;
8use crate::VectorMut;
9use crate::binaryview::BinaryScalar;
10use crate::binaryview::BinaryType;
11use crate::binaryview::BinaryViewScalar;
12use crate::binaryview::StringScalar;
13use crate::binaryview::StringType;
14use crate::bool::BoolScalar;
15use crate::decimal::DecimalScalar;
16use crate::fixed_size_list::FixedSizeListScalar;
17use crate::listview::ListViewScalar;
18use crate::match_each_scalar;
19use crate::null::NullScalar;
20use crate::primitive::PrimitiveScalar;
21use crate::struct_::StructScalar;
22
23/// Represents a scalar value of any supported type.
24#[derive(Clone, Debug, PartialEq)]
25pub enum Scalar {
26    /// Null scalars are always null.
27    Null(NullScalar),
28    /// Boolean scalars hold the boolean value in an [`Option`], where [`None`] represents null.
29    Bool(BoolScalar),
30    /// Decimal scalars hold the decimal value in a [`DScalar`](crate::decimal::DScalar), or else
31    /// [`None`] for null.
32    Decimal(DecimalScalar),
33    /// Primitive scalars hold the primitive value in a [`PScalar`](crate::primitive::PScalar), or
34    /// else [`None`] for null.
35    Primitive(PrimitiveScalar),
36    /// String scalars hold the string data in a [`BufferString`](vortex_buffer::BufferString), or
37    /// else [`None`] for null.
38    String(StringScalar),
39    /// Binary scalars hold the binary data in a [`ByteBuffer`](vortex_buffer::ByteBuffer), or else
40    /// [`None`] for null.
41    Binary(BinaryScalar),
42    /// Variable-size list scalars hold the list elements in a vector, or else [`None`] for null.
43    List(ListViewScalar),
44    /// Fixed-size list scalars hold the list elements in a vector, or else [`None`] for null.
45    FixedSizeList(FixedSizeListScalar),
46    /// Struct scalars are represented as a length-1 struct vector.
47    Struct(StructScalar),
48}
49
50impl ScalarOps for Scalar {
51    fn is_valid(&self) -> bool {
52        match_each_scalar!(self, |v| { v.is_valid() })
53    }
54
55    fn mask_validity(&mut self, mask: bool) {
56        match_each_scalar!(self, |v| { v.mask_validity(mask) })
57    }
58
59    fn repeat(&self, n: usize) -> VectorMut {
60        match_each_scalar!(self, |v| { v.repeat(n) })
61    }
62}
63
64impl Scalar {
65    /// Creates a zero/default scalar of the given [`DType`].
66    ///
67    /// For numeric types, this returns 0. For booleans, this returns `false`. For strings/binary,
68    /// this returns an empty value. For complex types, this creates a scalar with zero/default
69    /// elements.
70    ///
71    /// # Panics
72    ///
73    /// Panics if the dtype is [`DType::Null`], since null scalars cannot be zero.
74    pub fn zero(dtype: &DType) -> Self {
75        match dtype {
76            DType::Null => vortex_panic!("Cannot create zero scalar for Null dtype"),
77            DType::Bool(_) => BoolScalar::zero().into(),
78            DType::Primitive(ptype, _) => PrimitiveScalar::zero(*ptype).into(),
79            DType::Decimal(decimal_dtype, _) => DecimalScalar::zero(decimal_dtype).into(),
80            DType::Utf8(_) => BinaryViewScalar::<StringType>::zero().into(),
81            DType::Binary(_) => BinaryViewScalar::<BinaryType>::zero().into(),
82            DType::List(..) => ListViewScalar::zero(dtype).into(),
83            DType::FixedSizeList(..) => FixedSizeListScalar::zero(dtype).into(),
84            DType::Struct(..) => StructScalar::zero(dtype).into(),
85            DType::Extension(ext) => Self::zero(ext.storage_dtype()),
86        }
87    }
88
89    /// Creates a null scalar of the given [`DType`].
90    ///
91    /// # Panics
92    ///
93    /// Panics if the dtype is not nullable.
94    pub fn null(dtype: &DType) -> Self {
95        if !dtype.is_nullable() {
96            vortex_panic!(
97                "Cannot create null scalar for non-nullable dtype: {}",
98                dtype
99            );
100        }
101        match dtype {
102            DType::Null => NullScalar.into(),
103            DType::Bool(_) => BoolScalar::null().into(),
104            DType::Primitive(ptype, _) => PrimitiveScalar::null(*ptype).into(),
105            DType::Decimal(decimal_dtype, _) => DecimalScalar::null(decimal_dtype).into(),
106            DType::Utf8(_) => BinaryViewScalar::<StringType>::null().into(),
107            DType::Binary(_) => BinaryViewScalar::<BinaryType>::null().into(),
108            DType::List(..) => ListViewScalar::null(dtype).into(),
109            DType::FixedSizeList(..) => FixedSizeListScalar::null(dtype).into(),
110            DType::Struct(..) => StructScalar::null(dtype).into(),
111            DType::Extension(ext) => Self::null(ext.storage_dtype()),
112        }
113    }
114
115    /// Converts the [`Scalar`] into a [`NullScalar`].
116    pub fn into_null(self) -> NullScalar {
117        if let Scalar::Null(scalar) = self {
118            return scalar;
119        }
120        vortex_panic!("Cannot convert non-null Scalar into NullScalar");
121    }
122
123    /// Converts the [`Scalar`] into a [`BoolScalar`].
124    pub fn into_bool(self) -> BoolScalar {
125        if let Scalar::Bool(scalar) = self {
126            return scalar;
127        }
128        vortex_panic!("Cannot convert non-bool Scalar into BoolScalar");
129    }
130
131    /// Converts the [`Scalar`] into a [`BoolScalar`].
132    pub fn to_bool(&self) -> &BoolScalar {
133        if let Scalar::Bool(scalar) = self {
134            return scalar;
135        }
136        vortex_panic!("Cannot convert non-bool Scalar into BoolScalar");
137    }
138
139    /// Converts the [`Scalar`] into a [`DecimalScalar`].
140    pub fn into_decimal(self) -> DecimalScalar {
141        if let Scalar::Decimal(scalar) = self {
142            return scalar;
143        }
144        vortex_panic!("Cannot convert non-decimal Scalar into DecimalScalar");
145    }
146
147    /// Converts the [`Scalar`] into a [`PrimitiveScalar`].
148    pub fn into_primitive(self) -> PrimitiveScalar {
149        if let Scalar::Primitive(scalar) = self {
150            return scalar;
151        }
152        vortex_panic!("Cannot convert non-primitive Scalar into PrimitiveScalar");
153    }
154
155    /// Converts the [`Scalar`] into a [`StringScalar`].
156    pub fn into_string(self) -> StringScalar {
157        if let Scalar::String(scalar) = self {
158            return scalar;
159        }
160        vortex_panic!("Cannot convert non-string Scalar into StringScalar");
161    }
162
163    /// Converts the [`Scalar`] into a [`BinaryScalar`].
164    pub fn into_binary(self) -> BinaryScalar {
165        if let Scalar::Binary(scalar) = self {
166            return scalar;
167        }
168        vortex_panic!("Cannot convert non-binary Scalar into BinaryScalar");
169    }
170
171    /// Converts the [`Scalar`] into a [`ListViewScalar`].
172    pub fn into_list(self) -> ListViewScalar {
173        if let Scalar::List(scalar) = self {
174            return scalar;
175        }
176        vortex_panic!("Cannot convert non-list Scalar into ListViewScalar");
177    }
178
179    /// Converts the [`Scalar`] into a [`FixedSizeListScalar`].
180    pub fn into_fixed_size_list(self) -> FixedSizeListScalar {
181        if let Scalar::FixedSizeList(scalar) = self {
182            return scalar;
183        }
184        vortex_panic!("Cannot convert non-fixed-size-list Scalar into FixedSizeListScalar");
185    }
186
187    /// Converts the [`Scalar`] into a [`StructScalar`].
188    pub fn into_struct(self) -> StructScalar {
189        if let Scalar::Struct(scalar) = self {
190            return scalar;
191        }
192        vortex_panic!("Cannot convert non-struct Scalar into StructScalar");
193    }
194}
195
196impl Scalar {
197    /// Returns a reference to the inner [`NullScalar`].
198    pub fn as_null(&self) -> &NullScalar {
199        if let Scalar::Null(scalar) = self {
200            return scalar;
201        }
202        vortex_panic!("Cannot convert non-null Scalar into NullScalar");
203    }
204
205    /// Returns a reference to the inner [`BoolScalar`].
206    pub fn as_bool(&self) -> &BoolScalar {
207        if let Scalar::Bool(scalar) = self {
208            return scalar;
209        }
210        vortex_panic!("Cannot convert non-bool Scalar into BoolScalar");
211    }
212
213    /// Returns a reference to the inner [`DecimalScalar`].
214    pub fn as_decimal(&self) -> &DecimalScalar {
215        if let Scalar::Decimal(scalar) = self {
216            return scalar;
217        }
218        vortex_panic!("Cannot convert non-decimal Scalar into DecimalScalar");
219    }
220
221    /// Returns a reference to the inner [`PrimitiveScalar`].
222    pub fn as_primitive(&self) -> &PrimitiveScalar {
223        if let Scalar::Primitive(scalar) = self {
224            return scalar;
225        }
226        vortex_panic!("Cannot convert non-primitive Scalar into PrimitiveScalar");
227    }
228
229    /// Returns a reference to the inner [`StringScalar`].
230    pub fn as_string(&self) -> &StringScalar {
231        if let Scalar::String(scalar) = self {
232            return scalar;
233        }
234        vortex_panic!("Cannot convert non-string Scalar into StringScalar");
235    }
236
237    /// Returns a reference to the inner [`BinaryScalar`].
238    pub fn as_binary(&self) -> &BinaryScalar {
239        if let Scalar::Binary(scalar) = self {
240            return scalar;
241        }
242        vortex_panic!("Cannot convert non-binary Scalar into BinaryScalar");
243    }
244
245    /// Returns a reference to the inner [`ListViewScalar`].
246    pub fn as_list(&self) -> &ListViewScalar {
247        if let Scalar::List(scalar) = self {
248            return scalar;
249        }
250        vortex_panic!("Cannot convert non-list Scalar into ListViewScalar");
251    }
252
253    /// Returns a reference to the inner [`FixedSizeListScalar`].
254    pub fn as_fixed_size_list(&self) -> &FixedSizeListScalar {
255        if let Scalar::FixedSizeList(scalar) = self {
256            return scalar;
257        }
258        vortex_panic!("Cannot convert non-fixed-size-list Scalar into FixedSizeListScalar");
259    }
260
261    /// Returns a reference to the inner [`StructScalar`].
262    pub fn as_struct(&self) -> &StructScalar {
263        if let Scalar::Struct(scalar) = self {
264            return scalar;
265        }
266        vortex_panic!("Cannot convert non-struct Scalar into StructScalar");
267    }
268}