vortex_array/scalar/
cast.rs1use vortex_error::VortexExpect;
7use vortex_error::VortexResult;
8use vortex_error::vortex_bail;
9use vortex_error::vortex_ensure;
10
11use crate::dtype::DType;
12use crate::scalar::Scalar;
13
14impl Scalar {
15 pub fn cast(&self, target_dtype: &DType) -> VortexResult<Scalar> {
22 if self.dtype() == target_dtype {
24 return Ok(self.clone());
25 }
26
27 if self.dtype().eq_ignore_nullability(target_dtype) {
29 return Scalar::try_new(target_dtype.clone(), self.value().cloned());
32 }
33
34 if self.value().is_none() || matches!(self.dtype(), DType::Null) {
37 vortex_ensure!(
38 target_dtype.is_nullable(),
39 "Cannot cast null to {target_dtype}: target type is non-nullable"
40 );
41
42 return Scalar::try_new(target_dtype.clone(), self.value().cloned());
43 }
44
45 if let Some(ext_dtype) = target_dtype.as_extension_opt() {
48 let cast_storage_scalar_value = self.cast(ext_dtype.storage_dtype())?.into_value();
49 return Scalar::try_new(target_dtype.clone(), cast_storage_scalar_value);
50 }
51
52 match &self.dtype() {
53 DType::Null => unreachable!("Handled by the if case above"),
54 DType::Bool(_) => self.as_bool().cast(target_dtype),
55 DType::Primitive(..) => self.as_primitive().cast(target_dtype),
56 DType::Decimal(..) => self.as_decimal().cast(target_dtype),
57 DType::Utf8(_) => self.as_utf8().cast(target_dtype),
58 DType::Binary(_) => self.as_binary().cast(target_dtype),
59 DType::Struct(..) => self.as_struct().cast(target_dtype),
60 DType::List(..) | DType::FixedSizeList(..) => self.as_list().cast(target_dtype),
61 DType::Extension(..) => self.as_extension().cast(target_dtype),
62 DType::Variant(_) => vortex_bail!("Variant scalars can't be cast to {target_dtype}"),
63 }
64 }
65
66 pub fn into_nullable(self) -> Scalar {
68 let (dtype, value) = self.into_parts();
69 Self::try_new(dtype.as_nullable(), value)
70 .vortex_expect("Casting to nullable should always succeed")
71 }
72}