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

vortex-data / vortex / 16935267080

13 Aug 2025 11:00AM UTC coverage: 24.312% (-63.3%) from 87.658%
16935267080

Pull #4226

github

web-flow
Merge 81b48c7fb into baa6ea202
Pull Request #4226: Support converting TimestampTZ to and from duckdb

0 of 2 new or added lines in 1 file covered. (0.0%)

20666 existing lines in 469 files now uncovered.

8726 of 35892 relevant lines covered (24.31%)

147.74 hits per line

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

0.0
/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.
UNCOV
32
    pub fn as_primitive_typed(&self) -> PrimitiveTyped<'_> {
×
UNCOV
33
        matches!(self.dtype(), DType::Primitive(..))
×
UNCOV
34
            .then(|| PrimitiveTyped(self))
×
UNCOV
35
            .vortex_expect("Array does not have DType::Primitive")
×
UNCOV
36
    }
×
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<'_> {
UNCOV
100
    pub fn ptype(&self) -> PType {
×
UNCOV
101
        let DType::Primitive(ptype, _) = self.0.dtype() else {
×
102
            vortex_panic!("Expected Primitive DType")
×
103
        };
UNCOV
104
        *ptype
×
UNCOV
105
    }
×
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.
UNCOV
116
    pub fn value_unchecked(&self, idx: usize) -> PValue {
×
UNCOV
117
        self.0
×
UNCOV
118
            .scalar_at(idx)
×
UNCOV
119
            .vortex_expect("scalar at index")
×
UNCOV
120
            .as_primitive()
×
UNCOV
121
            .pvalue()
×
UNCOV
122
            .unwrap_or_else(|| PValue::zero(self.ptype()))
×
UNCOV
123
    }
×
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<'_> {
UNCOV
138
    fn index_cmp(&self, idx: usize, elem: &PValue) -> Option<Ordering> {
×
UNCOV
139
        assert!(self.0.all_valid().vortex_expect("all valid"));
×
UNCOV
140
        self.value_unchecked(idx).partial_cmp(elem)
×
UNCOV
141
    }
×
142

UNCOV
143
    fn index_len(&self) -> usize {
×
UNCOV
144
        self.0.len()
×
UNCOV
145
    }
×
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 · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc