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