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

vortex-data / vortex / 16339747936

17 Jul 2025 08:09AM UTC coverage: 80.702% (-0.002%) from 80.704%
16339747936

push

github

web-flow
Use ptr::default in Rust 1.88 (#3896)

Signed-off-by: Nicholas Gates <nick@nickgates.com>

0 of 14 new or added lines in 5 files covered. (0.0%)

2 existing lines in 1 file now uncovered.

41864 of 51875 relevant lines covered (80.7%)

157546.66 hits per line

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

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

4
//! FFI interface for working with Vortex Arrays.
5
use std::ffi::{c_int, c_void};
6

7
use vortex::dtype::half::f16;
8
use vortex::error::{VortexExpect, VortexUnwrap, vortex_err};
9
use vortex::{Array, ToCanonical};
10

11
use crate::arc_dyn_wrapper;
12
use crate::dtype::vx_dtype;
13
use crate::error::{try_or_default, vx_error};
14

15
arc_dyn_wrapper!(
16
    /// Base type for all Vortex arrays.
17
    ///
18
    /// All built-in Vortex array types can be safely cast to this type to pass into functions that
19
    /// expect a generic array type. e.g.
20
    ///
21
    /// ```cpp
22
    /// auto primitive_array = vx_array_primitive_new(...);
23
    /// vx_array_len((*vx_array) primitive_array));
24
    /// ```
25
    dyn Array,
26
    vx_array
27
);
28

29
/// Get the length of the array.
30
#[unsafe(no_mangle)]
31
pub unsafe extern "C-unwind" fn vx_array_len(array: *const vx_array) -> usize {
1✔
32
    vx_array::as_ref(array).len()
1✔
33
}
1✔
34

35
/// Get the [`crate::vx_dtype`] of the array.
36
///
37
/// The returned pointer is valid as long as the array is valid.
38
#[unsafe(no_mangle)]
39
pub unsafe extern "C-unwind" fn vx_array_dtype(array: *const vx_array) -> *const vx_dtype {
1✔
40
    vx_dtype::new_ref(vx_array::as_ref(array).dtype())
1✔
41
}
1✔
42

43
#[unsafe(no_mangle)]
44
pub unsafe extern "C-unwind" fn vx_array_get_field(
×
45
    array: *const vx_array,
×
46
    index: u32,
×
47
    error_out: *mut *mut vx_error,
×
48
) -> *const vx_array {
×
NEW
49
    try_or_default(error_out, || {
×
50
        let array = vx_array::as_ref(array);
×
51

52
        let field_array = array
×
53
            .to_struct()?
×
54
            .fields()
×
55
            .get(index as usize)
×
56
            .ok_or_else(|| vortex_err!("Field index out of bounds"))?
×
57
            .clone();
×
58

59
        Ok(vx_array::new(field_array))
×
60
    })
×
61
}
×
62

63
#[unsafe(no_mangle)]
64
pub unsafe extern "C-unwind" fn vx_array_slice(
×
65
    array: *const vx_array,
×
66
    start: u32,
×
67
    stop: u32,
×
68
    error_out: *mut *mut vx_error,
×
69
) -> *const vx_array {
×
70
    let array = vx_array::as_ref(array);
×
NEW
71
    try_or_default(error_out, || {
×
72
        let sliced = array.slice(start as usize, stop as usize)?;
×
73
        Ok(vx_array::new(sliced))
×
74
    })
×
75
}
×
76

77
#[unsafe(no_mangle)]
78
pub unsafe extern "C-unwind" fn vx_array_is_null(
×
79
    array: *const vx_array,
×
80
    index: u32,
×
81
    error_out: *mut *mut vx_error,
×
82
) -> bool {
×
83
    let array = vx_array::as_ref(array);
×
NEW
84
    try_or_default(error_out, || array.is_invalid(index as usize))
×
85
}
×
86

87
#[unsafe(no_mangle)]
88
pub unsafe extern "C-unwind" fn vx_array_null_count(
×
89
    array: *const vx_array,
×
90
    error_out: *mut *mut vx_error,
×
91
) -> u32 {
×
92
    let array = vx_array::as_ref(array);
×
NEW
93
    try_or_default(error_out, || Ok(array.invalid_count()?.try_into()?))
×
94
}
×
95

96
macro_rules! ffiarray_get_ptype {
97
    ($ptype:ident) => {
98
        paste::paste! {
99
            #[unsafe(no_mangle)]
100
            pub unsafe extern "C-unwind" fn [<vx_array_get_ $ptype>](array: *const vx_array, index: u32) -> $ptype {
3✔
101
                let array = vx_array::as_ref(array);
3✔
102
                let value = array.scalar_at(index as usize).vortex_expect("scalar_at");
3✔
103
                value.as_primitive()
3✔
104
                    .as_::<$ptype>()
3✔
105
                    .vortex_expect("as_")
3✔
106
                    .vortex_expect("null value")
3✔
107
            }
3✔
108

×
109
            #[unsafe(no_mangle)]
×
110
            pub unsafe extern "C-unwind" fn [<vx_array_get_storage_ $ptype>](array: *const vx_array, index: u32) -> $ptype {
×
111
                let array = vx_array::as_ref(array);
×
112
                let value = array.scalar_at(index as usize).vortex_expect("scalar_at");
×
113
                value.as_extension()
×
114
                    .storage()
×
115
                    .as_primitive()
×
116
                    .as_::<$ptype>()
×
117
                    .vortex_expect("as_")
×
118
                    .vortex_expect("null value")
×
119
            }
×
120
        }
121
    };
122
}
123

124
ffiarray_get_ptype!(u8);
125
ffiarray_get_ptype!(u16);
126
ffiarray_get_ptype!(u32);
127
ffiarray_get_ptype!(u64);
128
ffiarray_get_ptype!(i8);
129
ffiarray_get_ptype!(i16);
130
ffiarray_get_ptype!(i32);
131
ffiarray_get_ptype!(i64);
132
ffiarray_get_ptype!(f16);
133
ffiarray_get_ptype!(f32);
134
ffiarray_get_ptype!(f64);
135

136
/// Write the UTF-8 string at `index` in the array into the provided destination buffer, recording
137
/// the length in `len`.
138
#[unsafe(no_mangle)]
139
pub unsafe extern "C-unwind" fn vx_array_get_utf8(
×
140
    array: *const vx_array,
×
141
    index: u32,
×
142
    dst: *mut c_void,
×
143
    len: *mut c_int,
×
144
) {
×
145
    let array = vx_array::as_ref(array);
×
146
    let value = array.scalar_at(index as usize).vortex_expect("scalar_at");
×
147
    let utf8_scalar = value.as_utf8();
×
148
    if let Some(buffer) = utf8_scalar.value() {
×
149
        let bytes = buffer.as_bytes();
×
150
        let dst = unsafe { std::slice::from_raw_parts_mut(dst as *mut u8, bytes.len()) };
×
151
        dst.copy_from_slice(bytes);
×
152
        unsafe { *len = bytes.len().try_into().vortex_unwrap() };
×
153
    }
×
154
}
×
155

156
/// Write the UTF-8 string at `index` in the array into the provided destination buffer, recording
157
/// the length in `len`.
158
#[unsafe(no_mangle)]
159
pub unsafe extern "C-unwind" fn vx_array_get_binary(
×
160
    array: *const vx_array,
×
161
    index: u32,
×
162
    dst: *mut c_void,
×
163
    len: *mut c_int,
×
164
) {
×
165
    let array = vx_array::as_ref(array);
×
166
    let value = array.scalar_at(index as usize).vortex_expect("scalar_at");
×
167
    let utf8_scalar = value.as_binary();
×
168
    if let Some(bytes) = utf8_scalar.value() {
×
169
        let dst = unsafe { std::slice::from_raw_parts_mut(dst as *mut u8, bytes.len()) };
×
170
        dst.copy_from_slice(&bytes);
×
171
        unsafe { *len = bytes.len().try_into().vortex_unwrap() };
×
172
    }
×
173
}
×
174

175
#[cfg(test)]
176
mod tests {
177
    use vortex::arrays::PrimitiveArray;
178
    use vortex::buffer::buffer;
179
    use vortex::validity::Validity;
180

181
    use crate::array::{vx_array, vx_array_dtype, vx_array_free, vx_array_get_i32, vx_array_len};
182
    use crate::dtype::{vx_dtype_get_variant, vx_dtype_variant};
183

184
    #[test]
185
    fn test_simple() {
1✔
186
        unsafe {
187
            let primitive = PrimitiveArray::new(buffer![1i32, 2i32, 3i32], Validity::NonNullable);
1✔
188
            let ffi_array = vx_array::new(primitive.to_array());
1✔
189

190
            assert_eq!(vx_array_len(ffi_array), 3);
1✔
191

192
            let array_dtype = vx_array_dtype(ffi_array);
1✔
193
            assert_eq!(
1✔
194
                vx_dtype_get_variant(array_dtype),
1✔
195
                vx_dtype_variant::DTYPE_PRIMITIVE
196
            );
197

198
            assert_eq!(vx_array_get_i32(ffi_array, 0), 1);
1✔
199
            assert_eq!(vx_array_get_i32(ffi_array, 1), 2);
1✔
200
            assert_eq!(vx_array_get_i32(ffi_array, 2), 3);
1✔
201

202
            vx_array_free(ffi_array);
1✔
203
        }
204
    }
1✔
205
}
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

© 2025 Coveralls, Inc