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

vortex-data / vortex / 16728097825

04 Aug 2025 04:00PM UTC coverage: 48.355% (-35.1%) from 83.429%
16728097825

Pull #4108

github

web-flow
Merge 1b2d27fd8 into 649ba9576
Pull Request #4108: perf[vortex-array]: use all_valid instead of `invalid_count() == 0`

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

11596 existing lines in 378 files now uncovered.

18635 of 38538 relevant lines covered (48.35%)

151786.4 hits per line

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

23.3
/vortex-array/src/variants.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
//! This module defines extension functionality specific to each Vortex DType.
5
use std::cmp::Ordering;
6
use std::sync::Arc;
7

8
use vortex_dtype::{DType, ExtDType, FieldNames, PType};
9
use vortex_error::{VortexExpect, VortexResult, vortex_panic};
10
use vortex_scalar::PValue;
11

12
use crate::Array;
13
use crate::compute::sum;
14
use crate::search_sorted::IndexOrd;
15

16
impl dyn Array + '_ {
17
    /// Downcasts the array for null-specific behavior.
18
    pub fn as_null_typed(&self) -> NullTyped<'_> {
×
19
        matches!(self.dtype(), DType::Null)
×
20
            .then(|| NullTyped(self))
×
21
            .vortex_expect("Array does not have DType::Null")
×
22
    }
×
23

24
    /// Downcasts the array for bool-specific behavior.
UNCOV
25
    pub fn as_bool_typed(&self) -> BoolTyped<'_> {
×
UNCOV
26
        matches!(self.dtype(), DType::Bool(..))
×
UNCOV
27
            .then(|| BoolTyped(self))
×
UNCOV
28
            .vortex_expect("Array does not have DType::Bool")
×
UNCOV
29
    }
×
30

31
    /// Downcasts the array for primitive-specific behavior.
32
    pub fn as_primitive_typed(&self) -> PrimitiveTyped<'_> {
1,882✔
33
        matches!(self.dtype(), DType::Primitive(..))
1,882✔
34
            .then(|| PrimitiveTyped(self))
1,882✔
35
            .vortex_expect("Array does not have DType::Primitive")
1,882✔
36
    }
1,882✔
37

38
    /// Downcasts the array for decimal-specific behavior.
39
    pub fn as_decimal_typed(&self) -> DecimalTyped<'_> {
×
40
        matches!(self.dtype(), DType::Decimal(..))
×
41
            .then(|| DecimalTyped(self))
×
42
            .vortex_expect("Array does not have DType::Decimal")
×
43
    }
×
44

45
    /// Downcasts the array for utf8-specific behavior.
46
    pub fn as_utf8_typed(&self) -> Utf8Typed<'_> {
×
47
        matches!(self.dtype(), DType::Utf8(..))
×
48
            .then(|| Utf8Typed(self))
×
49
            .vortex_expect("Array does not have DType::Utf8")
×
50
    }
×
51

52
    /// Downcasts the array for binary-specific behavior.
53
    pub fn as_binary_typed(&self) -> BinaryTyped<'_> {
×
54
        matches!(self.dtype(), DType::Binary(..))
×
55
            .then(|| BinaryTyped(self))
×
56
            .vortex_expect("Array does not have DType::Binary")
×
57
    }
×
58

59
    /// Downcasts the array for struct-specific behavior.
UNCOV
60
    pub fn as_struct_typed(&self) -> StructTyped<'_> {
×
UNCOV
61
        matches!(self.dtype(), DType::Struct(..))
×
UNCOV
62
            .then(|| StructTyped(self))
×
UNCOV
63
            .vortex_expect("Array does not have DType::Struct")
×
UNCOV
64
    }
×
65

66
    /// Downcasts the array for list-specific behavior.
67
    pub fn as_list_typed(&self) -> ListTyped<'_> {
×
68
        matches!(self.dtype(), DType::List(..))
×
69
            .then(|| ListTyped(self))
×
70
            .vortex_expect("Array does not have DType::List")
×
71
    }
×
72

73
    /// Downcasts the array for extension-specific behavior.
74
    pub fn as_extension_typed(&self) -> ExtensionTyped<'_> {
×
75
        matches!(self.dtype(), DType::Extension(..))
×
76
            .then(|| ExtensionTyped(self))
×
77
            .vortex_expect("Array does not have DType::Extension")
×
78
    }
×
79
}
80

81
#[allow(dead_code)]
82
pub struct NullTyped<'a>(&'a dyn Array);
83

84
pub struct BoolTyped<'a>(&'a dyn Array);
85

86
impl BoolTyped<'_> {
UNCOV
87
    pub fn true_count(&self) -> VortexResult<usize> {
×
UNCOV
88
        let true_count = sum(self.0)?;
×
UNCOV
89
        Ok(true_count
×
UNCOV
90
            .as_primitive()
×
UNCOV
91
            .as_::<usize>()
×
UNCOV
92
            .vortex_expect("true count should never overflow usize")
×
UNCOV
93
            .vortex_expect("true count should never be null"))
×
UNCOV
94
    }
×
95
}
96

97
pub struct PrimitiveTyped<'a>(&'a dyn Array);
98

99
impl PrimitiveTyped<'_> {
100
    pub fn ptype(&self) -> PType {
66✔
101
        let DType::Primitive(ptype, _) = self.0.dtype() else {
66✔
102
            vortex_panic!("Expected Primitive DType")
×
103
        };
104
        *ptype
66✔
105
    }
66✔
106

107
    /// Return the primitive value at the given index.
UNCOV
108
    pub fn value(&self, idx: usize) -> Option<PValue> {
×
UNCOV
109
        self.0
×
UNCOV
110
            .is_valid(idx)
×
UNCOV
111
            .vortex_expect("is valid")
×
UNCOV
112
            .then(|| self.value_unchecked(idx))
×
UNCOV
113
    }
×
114

115
    /// Return the primitive value at the given index, ignoring nullability.
116
    pub fn value_unchecked(&self, idx: usize) -> PValue {
14,800✔
117
        self.0
14,800✔
118
            .scalar_at(idx)
14,800✔
119
            .vortex_expect("scalar at index")
14,800✔
120
            .as_primitive()
14,800✔
121
            .pvalue()
14,800✔
122
            .unwrap_or_else(|| PValue::zero(self.ptype()))
14,800✔
123
    }
14,800✔
124
}
125

126
impl IndexOrd<Option<PValue>> for PrimitiveTyped<'_> {
UNCOV
127
    fn index_cmp(&self, idx: usize, elem: &Option<PValue>) -> Option<Ordering> {
×
UNCOV
128
        self.value(idx).partial_cmp(elem)
×
UNCOV
129
    }
×
130

UNCOV
131
    fn index_len(&self) -> usize {
×
UNCOV
132
        self.0.len()
×
UNCOV
133
    }
×
134
}
135

136
// TODO(ngates): add generics to the `value` function and implement this over T.
137
impl IndexOrd<PValue> for PrimitiveTyped<'_> {
138
    fn index_cmp(&self, idx: usize, elem: &PValue) -> Option<Ordering> {
14,800✔
139
        assert!(self.0.all_valid().vortex_expect("all valid"));
14,800✔
140
        self.value_unchecked(idx).partial_cmp(elem)
14,800✔
141
    }
14,800✔
142

143
    fn index_len(&self) -> usize {
1,816✔
144
        self.0.len()
1,816✔
145
    }
1,816✔
146
}
147

148
#[allow(dead_code)]
149
pub struct Utf8Typed<'a>(&'a dyn Array);
150

151
#[allow(dead_code)]
152
pub struct BinaryTyped<'a>(&'a dyn Array);
153

154
#[allow(dead_code)]
155
pub struct DecimalTyped<'a>(&'a dyn Array);
156

157
pub struct StructTyped<'a>(&'a dyn Array);
158

159
impl StructTyped<'_> {
UNCOV
160
    pub fn names(&self) -> &FieldNames {
×
UNCOV
161
        let DType::Struct(st, _) = self.0.dtype() else {
×
162
            unreachable!()
×
163
        };
UNCOV
164
        st.names()
×
UNCOV
165
    }
×
166

167
    pub fn dtypes(&self) -> Vec<DType> {
×
168
        let DType::Struct(st, _) = self.0.dtype() else {
×
169
            unreachable!()
×
170
        };
171
        st.fields().collect()
×
172
    }
×
173

UNCOV
174
    pub fn nfields(&self) -> usize {
×
UNCOV
175
        self.names().len()
×
UNCOV
176
    }
×
177
}
178

179
#[allow(dead_code)]
180
pub struct ListTyped<'a>(&'a dyn Array);
181

182
pub struct ExtensionTyped<'a>(&'a dyn Array);
183

184
impl ExtensionTyped<'_> {
185
    /// Returns the extension logical [`DType`].
186
    pub fn ext_dtype(&self) -> &Arc<ExtDType> {
×
187
        let DType::Extension(ext_dtype) = self.0.dtype() else {
×
188
            vortex_panic!("Expected ExtDType")
×
189
        };
190
        ext_dtype
×
191
    }
×
192
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc