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) and
119 /// [`FixedSizeList`](crate::dtype::DType::FixedSizeList).
120 ///
121 /// # Panics
122 ///
123 /// Panics if the scalar does not have a [`List`](crate::dtype::DType::List) or [`FixedSizeList`](crate::dtype::DType::FixedSizeList) type.
124 pub fn as_list(&self) -> ListScalar<'_> {
125 self.as_list_opt()
126 .vortex_expect("Failed to convert scalar to list")
127 }
128
129 /// Returns a view of the scalar as a list scalar if it has a list type.
130 ///
131 /// Note that we use [`ListScalar`] to represent **both** [`List`](crate::dtype::DType::List) and
132 /// [`FixedSizeList`](crate::dtype::DType::FixedSizeList).
133 pub fn as_list_opt(&self) -> Option<ListScalar<'_>> {
134 ListScalar::try_new(self.dtype(), self.value()).ok()
135 }
136
137 /// Returns a view of the scalar as an extension scalar.
138 ///
139 /// # Panics
140 ///
141 /// Panics if the scalar does not have a [`Extension`](crate::dtype::DType::Extension) type.
142 pub fn as_extension(&self) -> ExtScalar<'_> {
143 self.as_extension_opt()
144 .vortex_expect("Failed to convert scalar to extension")
145 }
146
147 /// Returns a view of the scalar as an extension scalar if it has an extension type.
148 pub fn as_extension_opt(&self) -> Option<ExtScalar<'_>> {
149 if !self.dtype().is_extension() {
150 return None;
151 }
152
153 // SAFETY: Because we are a valid Scalar, we have already validated that the value is valid
154 // for this extension type.
155 Some(ExtScalar::new_unchecked(self.dtype(), self.value()))
156 }
157
158 /// Returns a view of the scalar as a variant scalar.
159 ///
160 /// # Panics
161 ///
162 /// Panics if the scalar does not have a [`Variant`](crate::dtype::DType::Variant) type.
163 pub fn as_variant(&self) -> VariantScalar<'_> {
164 self.as_variant_opt()
165 .vortex_expect("Failed to convert scalar to variant")
166 }
167
168 /// Returns a view of the scalar as a variant scalar if it has a variant type.
169 pub fn as_variant_opt(&self) -> Option<VariantScalar<'_>> {
170 VariantScalar::try_new(self.dtype(), self.value()).ok()
171 }
172}
173
174impl ScalarValue {
175 /// Returns the boolean value, panicking if the value is not a [`Bool`][ScalarValue::Bool].
176 pub fn as_bool(&self) -> bool {
177 match self {
178 ScalarValue::Bool(b) => *b,
179 _ => vortex_panic!("ScalarValue is not a Bool"),
180 }
181 }
182
183 /// Returns the primitive value, panicking if the value is not a
184 /// [`Primitive`][ScalarValue::Primitive].
185 pub fn as_primitive(&self) -> &PValue {
186 match self {
187 ScalarValue::Primitive(p) => p,
188 _ => vortex_panic!("ScalarValue is not a Primitive"),
189 }
190 }
191
192 /// Returns the decimal value, panicking if the value is not a
193 /// [`Decimal`][ScalarValue::Decimal].
194 pub fn as_decimal(&self) -> &DecimalValue {
195 match self {
196 ScalarValue::Decimal(d) => d,
197 _ => vortex_panic!("ScalarValue is not a Decimal"),
198 }
199 }
200
201 /// Returns the UTF-8 string value, panicking if the value is not a [`Utf8`][ScalarValue::Utf8].
202 pub fn as_utf8(&self) -> &BufferString {
203 match self {
204 ScalarValue::Utf8(s) => s,
205 _ => vortex_panic!("ScalarValue is not a Utf8"),
206 }
207 }
208
209 /// Returns the binary value, panicking if the value is not a [`Binary`][ScalarValue::Binary].
210 pub fn as_binary(&self) -> &ByteBuffer {
211 match self {
212 ScalarValue::Binary(b) => b,
213 _ => vortex_panic!("ScalarValue is not a Binary"),
214 }
215 }
216
217 /// Returns the list elements, panicking if the value is not a [`List`][ScalarValue::List].
218 pub fn as_list(&self) -> &[Option<ScalarValue>] {
219 match self {
220 ScalarValue::List(elements) => elements,
221 _ => vortex_panic!("ScalarValue is not a List"),
222 }
223 }
224
225 /// Returns the boolean value, panicking if the value is not a [`Bool`][ScalarValue::Bool].
226 pub fn into_bool(self) -> bool {
227 match self {
228 ScalarValue::Bool(b) => b,
229 _ => vortex_panic!("ScalarValue is not a Bool"),
230 }
231 }
232
233 /// Returns the primitive value, panicking if the value is not a
234 /// [`Primitive`][ScalarValue::Primitive].
235 pub fn into_primitive(self) -> PValue {
236 match self {
237 ScalarValue::Primitive(p) => p,
238 _ => vortex_panic!("ScalarValue is not a Primitive"),
239 }
240 }
241
242 /// Returns the decimal value, panicking if the value is not a
243 /// [`Decimal`][ScalarValue::Decimal].
244 pub fn into_decimal(self) -> DecimalValue {
245 match self {
246 ScalarValue::Decimal(d) => d,
247 _ => vortex_panic!("ScalarValue is not a Decimal"),
248 }
249 }
250
251 /// Returns the UTF-8 string value, panicking if the value is not a [`Utf8`][ScalarValue::Utf8].
252 pub fn into_utf8(self) -> BufferString {
253 match self {
254 ScalarValue::Utf8(s) => s,
255 _ => vortex_panic!("ScalarValue is not a Utf8"),
256 }
257 }
258
259 /// Returns the binary value, panicking if the value is not a [`Binary`][ScalarValue::Binary].
260 pub fn into_binary(self) -> ByteBuffer {
261 match self {
262 ScalarValue::Binary(b) => b,
263 _ => vortex_panic!("ScalarValue is not a Binary"),
264 }
265 }
266
267 /// Returns the list elements, panicking if the value is not a [`List`][ScalarValue::List].
268 pub fn into_list(self) -> Vec<Option<ScalarValue>> {
269 match self {
270 ScalarValue::List(elements) => elements,
271 _ => vortex_panic!("ScalarValue is not a List"),
272 }
273 }
274
275 /// Returns the row-specific scalar wrapped by a variant, panicking if the value is not a
276 /// variant.
277 pub fn as_variant(&self) -> &Scalar {
278 match self {
279 ScalarValue::Variant(value) => value,
280 _ => vortex_panic!("ScalarValue is not a Variant"),
281 }
282 }
283
284 /// Returns the row-specific scalar wrapped by a variant, panicking if the value is not a
285 /// variant.
286 pub fn into_variant(self) -> Scalar {
287 match self {
288 ScalarValue::Variant(value) => *value,
289 _ => vortex_panic!("ScalarValue is not a Variant"),
290 }
291 }
292}