vortex_compute/cast/
struct_.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_dtype::DType;
5use vortex_error::VortexResult;
6use vortex_error::vortex_bail;
7use vortex_vector::Scalar;
8use vortex_vector::ScalarOps;
9use vortex_vector::Vector;
10use vortex_vector::VectorOps;
11use vortex_vector::struct_::StructScalar;
12use vortex_vector::struct_::StructVector;
13use vortex_vector::vector_matches_dtype;
14
15use crate::cast::Cast;
16use crate::cast::try_cast_scalar_common;
17use crate::cast::try_cast_vector_common;
18
19/// Checks if a struct vector's fields match the given struct fields dtype.
20fn struct_fields_match(vector: &StructVector, fields: &vortex_dtype::StructFields) -> bool {
21    if fields.nfields() != vector.fields().len() {
22        return false;
23    }
24    for (field_dtype, field_vector) in fields.fields().zip(vector.fields().iter()) {
25        if !vector_matches_dtype(field_vector, &field_dtype) {
26            return false;
27        }
28    }
29    true
30}
31
32impl Cast for StructVector {
33    type Output = Vector;
34
35    /// Casts to Struct (identity with same fields and compatible nullability).
36    fn cast(&self, target_dtype: &DType) -> VortexResult<Vector> {
37        if let Some(result) = try_cast_vector_common(self, target_dtype)? {
38            return Ok(result);
39        }
40
41        match target_dtype {
42            // Identity cast: same fields and compatible nullability.
43            DType::Struct(fields, n)
44                if struct_fields_match(self, fields)
45                    && (n.is_nullable() || self.validity().all_true()) =>
46            {
47                Ok(self.clone().into())
48            }
49            DType::Struct(..) => {
50                vortex_bail!(
51                    "Cannot cast StructVector to {} (incompatible fields or nullability)",
52                    target_dtype
53                );
54            }
55            _ => {
56                vortex_bail!("Cannot cast StructVector to {}", target_dtype);
57            }
58        }
59    }
60}
61
62impl Cast for StructScalar {
63    type Output = Scalar;
64
65    /// Casts to Struct (identity with same fields and compatible nullability).
66    fn cast(&self, target_dtype: &DType) -> VortexResult<Scalar> {
67        if let Some(result) = try_cast_scalar_common(self, target_dtype)? {
68            return Ok(result);
69        }
70
71        match target_dtype {
72            // Identity cast: same fields and compatible nullability.
73            DType::Struct(fields, n)
74                if struct_fields_match(self.value(), fields)
75                    && (n.is_nullable() || self.is_valid()) =>
76            {
77                Ok(self.clone().into())
78            }
79            DType::Struct(..) => {
80                vortex_bail!(
81                    "Cannot cast StructScalar to {} (incompatible fields or nullability)",
82                    target_dtype
83                );
84            }
85            _ => {
86                vortex_bail!("Cannot cast StructScalar to {}", target_dtype);
87            }
88        }
89    }
90}