• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16729059657

04 Aug 2025 04:45PM UTC coverage: 83.417% (-0.3%) from 83.688%
16729059657

Pull #4109

github

web-flow
Merge 824cda705 into 7a35bb974
Pull Request #4109: Revert "feat: implement Cast Kernel everywhere"

13 of 13 new or added lines in 1 file covered. (100.0%)

45 existing lines in 12 files now uncovered.

46430 of 55660 relevant lines covered (83.42%)

449843.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.02
/vortex-array/src/arrays/primitive/compute/cast.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use vortex_buffer::{Buffer, BufferMut};
5
use vortex_dtype::{DType, NativePType, Nullability, match_each_native_ptype};
6
use vortex_error::{VortexResult, vortex_bail, vortex_err};
7

8
use crate::arrays::PrimitiveVTable;
9
use crate::arrays::primitive::PrimitiveArray;
10
use crate::compute::{CastKernel, CastKernelAdapter};
11
use crate::validity::Validity;
12
use crate::vtable::ValidityHelper;
13
use crate::{ArrayRef, IntoArray, register_kernel};
14

15
impl CastKernel for PrimitiveVTable {
16
    fn cast(&self, array: &PrimitiveArray, dtype: &DType) -> VortexResult<Option<ArrayRef>> {
14,327✔
17
        let DType::Primitive(new_ptype, new_nullability) = dtype else {
14,327✔
18
            return Ok(None);
×
19
        };
20
        let (new_ptype, new_nullability) = (*new_ptype, *new_nullability);
14,327✔
21

22
        // First, check that the cast is compatible with the source array's validity
23
        let new_validity = if array.dtype().nullability() == new_nullability {
14,327✔
24
            array.validity().clone()
8,357✔
25
        } else if new_nullability == Nullability::Nullable {
5,970✔
26
            // from non-nullable to nullable
27
            array.validity().clone().into_nullable()
5,773✔
28
        } else if new_nullability == Nullability::NonNullable && array.validity().all_valid()? {
197✔
29
            // from nullable but all valid, to non-nullable
30
            Validity::NonNullable
119✔
31
        } else {
32
            vortex_bail!(
78✔
33
                "invalid cast from nullable to non-nullable, since source array actually contains nulls"
78✔
34
            );
35
        };
36

37
        // If the bit width is the same, we can short-circuit and simply update the validity
38
        if array.ptype() == new_ptype {
14,249✔
39
            return Ok(Some(
5,129✔
40
                PrimitiveArray::from_byte_buffer(
5,129✔
41
                    array.byte_buffer().clone(),
5,129✔
42
                    array.ptype(),
5,129✔
43
                    new_validity,
5,129✔
44
                )
5,129✔
45
                .into_array(),
5,129✔
46
            ));
5,129✔
47
        }
9,120✔
48

49
        // Otherwise, we need to cast the values one-by-one
50
        match_each_native_ptype!(new_ptype, |T| {
9,120✔
51
            Ok(Some(
52
                PrimitiveArray::new(cast::<T>(array)?, new_validity).into_array(),
4,562✔
53
            ))
54
        })
55
    }
14,327✔
56
}
57

58
register_kernel!(CastKernelAdapter(PrimitiveVTable).lift());
59

60
fn cast<T: NativePType>(array: &PrimitiveArray) -> VortexResult<Buffer<T>> {
9,120✔
61
    let mut buffer = BufferMut::with_capacity(array.len());
9,120✔
62
    match_each_native_ptype!(array.ptype(), |P| {
9,120✔
63
        for item in array.as_slice::<P>() {
421✔
64
            let item = T::from(*item).ok_or_else(
421✔
65
                || vortex_err!(ComputeError: "Failed to cast {} to {:?}", item, T::PTYPE),
609✔
UNCOV
66
            )?;
×
67
            // SAFETY: we've pre-allocated the required capacity
68
            unsafe { buffer.push_unchecked(item) }
421✔
69
        }
70
    });
71
    Ok(buffer.freeze())
8,511✔
72
}
9,120✔
73

74
#[cfg(test)]
75
mod test {
76
    use vortex_buffer::buffer;
77
    use vortex_dtype::{DType, Nullability, PType};
78
    use vortex_error::VortexError;
79

80
    use crate::IntoArray;
81
    use crate::arrays::PrimitiveArray;
82
    use crate::canonical::ToCanonical;
83
    use crate::compute::cast;
84
    use crate::validity::Validity;
85
    use crate::vtable::ValidityHelper;
86

87
    #[test]
88
    fn cast_u32_u8() {
1✔
89
        let arr = buffer![0u32, 10, 200].into_array();
1✔
90

91
        // cast from u32 to u8
92
        let p = cast(&arr, PType::U8.into())
1✔
93
            .unwrap()
1✔
94
            .to_primitive()
1✔
95
            .unwrap();
1✔
96
        assert_eq!(p.as_slice::<u8>(), vec![0u8, 10, 200]);
1✔
97
        assert_eq!(p.validity(), &Validity::NonNullable);
1✔
98

99
        // to nullable
100
        let p = cast(
1✔
101
            p.as_ref(),
1✔
102
            &DType::Primitive(PType::U8, Nullability::Nullable),
1✔
103
        )
1✔
104
        .unwrap()
1✔
105
        .to_primitive()
1✔
106
        .unwrap();
1✔
107
        assert_eq!(p.as_slice::<u8>(), vec![0u8, 10, 200]);
1✔
108
        assert_eq!(p.validity(), &Validity::AllValid);
1✔
109

110
        // back to non-nullable
111
        let p = cast(
1✔
112
            p.as_ref(),
1✔
113
            &DType::Primitive(PType::U8, Nullability::NonNullable),
1✔
114
        )
1✔
115
        .unwrap()
1✔
116
        .to_primitive()
1✔
117
        .unwrap();
1✔
118
        assert_eq!(p.as_slice::<u8>(), vec![0u8, 10, 200]);
1✔
119
        assert_eq!(p.validity(), &Validity::NonNullable);
1✔
120

121
        // to nullable u32
122
        let p = cast(
1✔
123
            p.as_ref(),
1✔
124
            &DType::Primitive(PType::U32, Nullability::Nullable),
1✔
125
        )
1✔
126
        .unwrap()
1✔
127
        .to_primitive()
1✔
128
        .unwrap();
1✔
129
        assert_eq!(p.as_slice::<u32>(), vec![0u32, 10, 200]);
1✔
130
        assert_eq!(p.validity(), &Validity::AllValid);
1✔
131

132
        // to non-nullable u8
133
        let p = cast(
1✔
134
            p.as_ref(),
1✔
135
            &DType::Primitive(PType::U8, Nullability::NonNullable),
1✔
136
        )
1✔
137
        .unwrap()
1✔
138
        .to_primitive()
1✔
139
        .unwrap();
1✔
140
        assert_eq!(p.as_slice::<u8>(), vec![0u8, 10, 200]);
1✔
141
        assert_eq!(p.validity(), &Validity::NonNullable);
1✔
142
    }
1✔
143

144
    #[test]
145
    fn cast_u32_f32() {
1✔
146
        let arr = buffer![0u32, 10, 200].into_array();
1✔
147
        let u8arr = cast(&arr, PType::F32.into())
1✔
148
            .unwrap()
1✔
149
            .to_primitive()
1✔
150
            .unwrap();
1✔
151
        assert_eq!(u8arr.as_slice::<f32>(), vec![0.0f32, 10., 200.]);
1✔
152
    }
1✔
153

154
    #[test]
155
    fn cast_i32_u32() {
1✔
156
        let arr = buffer![-1i32].into_array();
1✔
157
        let error = cast(&arr, PType::U32.into()).err().unwrap();
1✔
158
        let VortexError::ComputeError(s, _) = error else {
1✔
159
            unreachable!()
160
        };
161
        assert_eq!(s.to_string(), "Failed to cast -1 to U32");
1✔
162
    }
1✔
163

164
    #[test]
165
    fn cast_array_with_nulls_to_nonnullable() {
1✔
166
        let arr = PrimitiveArray::from_option_iter([Some(-1i32), None, Some(10)]);
1✔
167
        let err = cast(arr.as_ref(), PType::I32.into()).unwrap_err();
1✔
168
        let VortexError::InvalidArgument(s, _) = err else {
1✔
169
            unreachable!()
170
        };
171
        assert_eq!(
1✔
172
            s.to_string(),
1✔
173
            "invalid cast from nullable to non-nullable, since source array actually contains nulls"
174
        );
175
    }
1✔
176
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc