Skip to main content

vortex_array/scalar/
downcast.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Scalar downcasting methods to typed views.
5
6use vortex_buffer::BufferString;
7use vortex_buffer::ByteBuffer;
8use vortex_error::VortexExpect;
9use vortex_error::vortex_panic;
10
11use crate::scalar::BinaryScalar;
12use crate::scalar::BoolScalar;
13use crate::scalar::DecimalScalar;
14use crate::scalar::DecimalValue;
15use crate::scalar::ExtScalar;
16use crate::scalar::ListScalar;
17use crate::scalar::PValue;
18use crate::scalar::PrimitiveScalar;
19use crate::scalar::Scalar;
20use crate::scalar::ScalarValue;
21use crate::scalar::StructScalar;
22use crate::scalar::UnionScalar;
23use crate::scalar::UnionValue;
24use crate::scalar::Utf8Scalar;
25use crate::scalar::VariantScalar;
26
27impl Scalar {
28    /// Returns a view of the scalar as a boolean scalar.
29    ///
30    /// # Panics
31    ///
32    /// Panics if the scalar does not have a [`Bool`](crate::dtype::DType::Bool) type.
33    pub fn as_bool(&self) -> BoolScalar<'_> {
34        self.as_bool_opt()
35            .vortex_expect("Failed to convert scalar to bool")
36    }
37
38    /// Returns a view of the scalar as a boolean scalar if it has a boolean type.
39    pub fn as_bool_opt(&self) -> Option<BoolScalar<'_>> {
40        BoolScalar::try_new(self.dtype(), self.value()).ok()
41    }
42
43    /// Returns a view of the scalar as a primitive scalar.
44    ///
45    /// # Panics
46    ///
47    /// Panics if the scalar does not have a [`Primitive`](crate::dtype::DType::Primitive) type.
48    pub fn as_primitive(&self) -> PrimitiveScalar<'_> {
49        self.as_primitive_opt()
50            .vortex_expect("Failed to convert scalar to primitive")
51    }
52
53    /// Returns a view of the scalar as a primitive scalar if it has a primitive type.
54    pub fn as_primitive_opt(&self) -> Option<PrimitiveScalar<'_>> {
55        PrimitiveScalar::try_new(self.dtype(), self.value()).ok()
56    }
57
58    /// Returns a view of the scalar as a decimal scalar.
59    ///
60    /// # Panics
61    ///
62    /// Panics if the scalar does not have a [`Decimal`](crate::dtype::DType::Decimal) type.
63    pub fn as_decimal(&self) -> DecimalScalar<'_> {
64        self.as_decimal_opt()
65            .vortex_expect("Failed to convert scalar to decimal")
66    }
67
68    /// Returns a view of the scalar as a decimal scalar if it has a decimal type.
69    pub fn as_decimal_opt(&self) -> Option<DecimalScalar<'_>> {
70        DecimalScalar::try_new(self.dtype(), self.value()).ok()
71    }
72
73    /// Returns a view of the scalar as a UTF-8 string scalar.
74    ///
75    /// # Panics
76    ///
77    /// Panics if the scalar does not have a [`Utf8`](crate::dtype::DType::Utf8) type.
78    pub fn as_utf8(&self) -> Utf8Scalar<'_> {
79        self.as_utf8_opt()
80            .vortex_expect("Failed to convert scalar to utf8")
81    }
82
83    /// Returns a view of the scalar as a UTF-8 string scalar if it has a UTF-8 type.
84    pub fn as_utf8_opt(&self) -> Option<Utf8Scalar<'_>> {
85        Utf8Scalar::try_new(self.dtype(), self.value()).ok()
86    }
87
88    /// Returns a view of the scalar as a binary scalar.
89    ///
90    /// # Panics
91    ///
92    /// Panics if the scalar does not have a [`Binary`](crate::dtype::DType::Binary) type.
93    pub fn as_binary(&self) -> BinaryScalar<'_> {
94        self.as_binary_opt()
95            .vortex_expect("Failed to convert scalar to binary")
96    }
97
98    /// Returns a view of the scalar as a binary scalar if it has a binary type.
99    pub fn as_binary_opt(&self) -> Option<BinaryScalar<'_>> {
100        BinaryScalar::try_new(self.dtype(), self.value()).ok()
101    }
102
103    /// Returns a view of the scalar as a struct scalar.
104    ///
105    /// # Panics
106    ///
107    /// Panics if the scalar does not have a [`Struct`](crate::dtype::DType::Struct) type.
108    pub fn as_struct(&self) -> StructScalar<'_> {
109        self.as_struct_opt()
110            .vortex_expect("Failed to convert scalar to struct")
111    }
112
113    /// Returns a view of the scalar as a struct scalar if it has a struct type.
114    pub fn as_struct_opt(&self) -> Option<StructScalar<'_>> {
115        StructScalar::try_new(self.dtype(), self.value()).ok()
116    }
117
118    /// Returns a view of the scalar as a list scalar.
119    ///
120    /// Note that we use [`ListScalar`] to represent **both** [`List`](crate::dtype::DType::List)
121    /// and [`FixedSizeList`](crate::dtype::DType::FixedSizeList).
122    ///
123    /// # Panics
124    ///
125    /// Panics if the scalar does not have a [`List`](crate::dtype::DType::List) or
126    /// [`FixedSizeList`](crate::dtype::DType::FixedSizeList) type.
127    pub fn as_list(&self) -> ListScalar<'_> {
128        self.as_list_opt()
129            .vortex_expect("Failed to convert scalar to list")
130    }
131
132    /// Returns a view of the scalar as a list scalar if it has a list type.
133    ///
134    /// Note that we use [`ListScalar`] to represent **both** [`List`](crate::dtype::DType::List)
135    /// and [`FixedSizeList`](crate::dtype::DType::FixedSizeList).
136    pub fn as_list_opt(&self) -> Option<ListScalar<'_>> {
137        ListScalar::try_new(self.dtype(), self.value()).ok()
138    }
139
140    /// Returns a view of the scalar as an extension scalar.
141    ///
142    /// # Panics
143    ///
144    /// Panics if the scalar does not have a [`Extension`](crate::dtype::DType::Extension) type.
145    pub fn as_extension(&self) -> ExtScalar<'_> {
146        self.as_extension_opt()
147            .vortex_expect("Failed to convert scalar to extension")
148    }
149
150    /// Returns a view of the scalar as an extension scalar if it has an extension type.
151    pub fn as_extension_opt(&self) -> Option<ExtScalar<'_>> {
152        if !self.dtype().is_extension() {
153            return None;
154        }
155
156        // SAFETY: Because we are a valid Scalar, we have already validated that the value is valid
157        // for this extension type.
158        Some(ExtScalar::new_unchecked(self.dtype(), self.value()))
159    }
160
161    /// Returns a view of the scalar as a union scalar.
162    ///
163    /// # Panics
164    ///
165    /// Panics if the scalar does not have a [`Union`](crate::dtype::DType::Union) type.
166    pub fn as_union(&self) -> UnionScalar<'_> {
167        self.as_union_opt()
168            .vortex_expect("Failed to convert scalar to union")
169    }
170
171    /// Returns a view of the scalar as a union scalar if it has a union dtype.
172    ///
173    /// [`None`] means the scalar's dtype is not [`DType::Union`](crate::dtype::DType); it does not
174    /// describe the scalar's nullness.
175    ///
176    /// An outer null union still returns `Some(UnionScalar)` and can be inspected with
177    /// [`UnionScalar::is_null`](crate::scalar::UnionScalar::is_null).
178    pub fn as_union_opt(&self) -> Option<UnionScalar<'_>> {
179        if !self.dtype().is_union() {
180            return None;
181        }
182
183        // Scalar construction has already validated the value against this union dtype.
184        Some(UnionScalar::new_unchecked(self.dtype(), self.value()))
185    }
186
187    /// Returns a view of the scalar as a variant scalar.
188    ///
189    /// # Panics
190    ///
191    /// Panics if the scalar does not have a [`Variant`](crate::dtype::DType::Variant) type.
192    pub fn as_variant(&self) -> VariantScalar<'_> {
193        self.as_variant_opt()
194            .vortex_expect("Failed to convert scalar to variant")
195    }
196
197    /// Returns a view of the scalar as a variant scalar if it has a variant type.
198    pub fn as_variant_opt(&self) -> Option<VariantScalar<'_>> {
199        VariantScalar::try_new(self.dtype(), self.value()).ok()
200    }
201}
202
203impl ScalarValue {
204    /// Returns the boolean value, panicking if the value is not a [`Bool`](ScalarValue::Bool).
205    pub fn as_bool(&self) -> bool {
206        match self {
207            ScalarValue::Bool(b) => *b,
208            _ => vortex_panic!("ScalarValue is not a Bool"),
209        }
210    }
211
212    /// Returns the primitive value, panicking if the value is not a
213    /// [`Primitive`](ScalarValue::Primitive).
214    pub fn as_primitive(&self) -> &PValue {
215        match self {
216            ScalarValue::Primitive(p) => p,
217            _ => vortex_panic!("ScalarValue is not a Primitive"),
218        }
219    }
220
221    /// Returns the decimal value, panicking if the value is not a
222    /// [`Decimal`](ScalarValue::Decimal).
223    pub fn as_decimal(&self) -> &DecimalValue {
224        match self {
225            ScalarValue::Decimal(d) => d,
226            _ => vortex_panic!("ScalarValue is not a Decimal"),
227        }
228    }
229
230    /// Returns the UTF-8 string value, panicking if the value is not a [`Utf8`](ScalarValue::Utf8).
231    pub fn as_utf8(&self) -> &BufferString {
232        match self {
233            ScalarValue::Utf8(s) => s,
234            _ => vortex_panic!("ScalarValue is not a Utf8"),
235        }
236    }
237
238    /// Returns the binary value, panicking if the value is not a [`Binary`](ScalarValue::Binary).
239    pub fn as_binary(&self) -> &ByteBuffer {
240        match self {
241            ScalarValue::Binary(b) => b,
242            _ => vortex_panic!("ScalarValue is not a Binary"),
243        }
244    }
245
246    /// Returns the tuple elements, panicking if the value is not a [`Tuple`](ScalarValue::Tuple).
247    pub fn as_list(&self) -> &[Option<ScalarValue>] {
248        match self {
249            ScalarValue::Tuple(elements) => elements,
250            _ => vortex_panic!("ScalarValue is not a Tuple"),
251        }
252    }
253
254    /// Returns the boolean value, panicking if the value is not a [`Bool`](ScalarValue::Bool).
255    pub fn into_bool(self) -> bool {
256        match self {
257            ScalarValue::Bool(b) => b,
258            _ => vortex_panic!("ScalarValue is not a Bool"),
259        }
260    }
261
262    /// Returns the primitive value, panicking if the value is not a
263    /// [`Primitive`](ScalarValue::Primitive).
264    pub fn into_primitive(self) -> PValue {
265        match self {
266            ScalarValue::Primitive(p) => p,
267            _ => vortex_panic!("ScalarValue is not a Primitive"),
268        }
269    }
270
271    /// Returns the decimal value, panicking if the value is not a
272    /// [`Decimal`](ScalarValue::Decimal).
273    pub fn into_decimal(self) -> DecimalValue {
274        match self {
275            ScalarValue::Decimal(d) => d,
276            _ => vortex_panic!("ScalarValue is not a Decimal"),
277        }
278    }
279
280    /// Returns the UTF-8 string value, panicking if the value is not a [`Utf8`](ScalarValue::Utf8).
281    pub fn into_utf8(self) -> BufferString {
282        match self {
283            ScalarValue::Utf8(s) => s,
284            _ => vortex_panic!("ScalarValue is not a Utf8"),
285        }
286    }
287
288    /// Returns the binary value, panicking if the value is not a [`Binary`](ScalarValue::Binary).
289    pub fn into_binary(self) -> ByteBuffer {
290        match self {
291            ScalarValue::Binary(b) => b,
292            _ => vortex_panic!("ScalarValue is not a Binary"),
293        }
294    }
295
296    /// Returns the tuple elements, panicking if the value is not a [`Tuple`](ScalarValue::Tuple).
297    pub fn into_list(self) -> Vec<Option<ScalarValue>> {
298        match self {
299            ScalarValue::Tuple(elements) => elements,
300            _ => vortex_panic!("ScalarValue is not a Tuple"),
301        }
302    }
303
304    /// Returns the union value, panicking if the value is not a [`Union`](ScalarValue::Union).
305    pub fn as_union(&self) -> &UnionValue {
306        match self {
307            ScalarValue::Union(value) => value,
308            _ => vortex_panic!("ScalarValue is not a Union"),
309        }
310    }
311
312    /// Returns the union value, panicking if the value is not a [`Union`](ScalarValue::Union).
313    pub fn into_union(self) -> UnionValue {
314        match self {
315            ScalarValue::Union(value) => value,
316            _ => vortex_panic!("ScalarValue is not a Union"),
317        }
318    }
319
320    /// Returns the row-specific scalar wrapped by a variant, panicking if the value is not a
321    /// variant.
322    pub fn as_variant(&self) -> &Scalar {
323        match self {
324            ScalarValue::Variant(value) => value,
325            _ => vortex_panic!("ScalarValue is not a Variant"),
326        }
327    }
328
329    /// Returns the row-specific scalar wrapped by a variant, panicking if the value is not a
330    /// variant.
331    pub fn into_variant(self) -> Scalar {
332        match self {
333            ScalarValue::Variant(value) => *value,
334            _ => vortex_panic!("ScalarValue is not a Variant"),
335        }
336    }
337}