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