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