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}