vortex_array/scalar/
cast.rs1use vortex_error::VortexExpect;
7use vortex_error::VortexResult;
8use vortex_error::vortex_bail;
9use vortex_error::vortex_ensure;
10use vortex_error::vortex_err;
11
12use crate::dtype::DType;
13use crate::scalar::Scalar;
14
15impl Scalar {
16 pub fn cast(&self, target_dtype: &DType) -> VortexResult<Scalar> {
23 if self.dtype() == target_dtype {
25 return Ok(self.clone());
26 }
27
28 if self.dtype().eq_ignore_nullability(target_dtype) {
30 return Scalar::try_new(target_dtype.clone(), self.value().cloned());
33 }
34
35 if let (Some(source), Some(target)) = (self.dtype().as_map_opt(), target_dtype.as_map_opt())
36 && target.keys_sorted()
37 && !source.keys_sorted()
38 {
39 return Err(vortex_err!(
40 "Cannot cast {} to {target_dtype}: source does not assert sorted map keys",
41 self.dtype()
42 ));
43 }
44
45 if self.value().is_none() || matches!(self.dtype(), DType::Null) {
48 vortex_ensure!(
49 target_dtype.is_nullable(),
50 "Cannot cast null to {target_dtype}: target type is non-nullable"
51 );
52
53 return Scalar::try_new(target_dtype.clone(), self.value().cloned());
54 }
55
56 if let Some(ext_dtype) = target_dtype.as_extension_opt() {
59 let cast_storage_scalar_value = self.cast(ext_dtype.storage_dtype())?.into_value();
60 return Scalar::try_new(target_dtype.clone(), cast_storage_scalar_value);
61 }
62
63 match &self.dtype() {
64 DType::Null => unreachable!("Handled by the if case above"),
65 DType::Bool(_) => self.as_bool().cast(target_dtype),
66 DType::Primitive(..) => self.as_primitive().cast(target_dtype),
67 DType::Decimal(..) => self.as_decimal().cast(target_dtype),
68 DType::Utf8(_) => self.as_utf8().cast(target_dtype),
69 DType::Binary(_) => self.as_binary().cast(target_dtype),
70 DType::List(..) | DType::FixedSizeList(..) => self.as_list().cast(target_dtype),
71 DType::Map(..) => self.as_map().cast(target_dtype),
72 DType::Struct(..) => self.as_struct().cast(target_dtype),
73 DType::Union(..) => vortex_bail!(
74 "union scalar cast from {} to {target_dtype} is not supported (yet)",
75 self.dtype()
76 ),
77 DType::Variant(_) => vortex_bail!("Variant scalars can't be cast to {target_dtype}"),
78 DType::Extension(..) => self.as_extension().cast(target_dtype),
79 }
80 }
81
82 pub fn into_nullable(self) -> Scalar {
84 let (dtype, value) = self.into_parts();
85 Self::try_new(dtype.as_nullable(), value)
86 .vortex_expect("Casting to nullable should always succeed")
87 }
88}