22// SPDX-FileCopyrightText: Copyright the Vortex contributors
33
44//! FFI interface for working with Vortex Arrays.
5- use std:: ffi :: { c_int , c_void } ;
6- use std:: slice ;
5+ use std:: ptr ;
6+ use std:: sync :: Arc ;
77
88use vortex:: dtype:: half:: f16;
9- use vortex:: error:: { VortexExpect , VortexUnwrap , vortex_err} ;
9+ use vortex:: error:: { VortexExpect , vortex_err} ;
1010use vortex:: { Array , ToCanonical } ;
1111
1212use crate :: arc_dyn_wrapper;
13+ use crate :: binary:: vx_binary;
1314use crate :: dtype:: vx_dtype;
1415use crate :: error:: { try_or_default, vx_error} ;
16+ use crate :: string:: vx_string;
1517
1618arc_dyn_wrapper ! (
1719 /// Base type for all Vortex arrays.
@@ -133,48 +135,42 @@ ffiarray_get_ptype!(f16);
133135ffiarray_get_ptype ! ( f32 ) ;
134136ffiarray_get_ptype ! ( f64 ) ;
135137
136- /// Write the UTF -8 string at `index` in the array into the provided destination buffer, recording
137- /// the length in `len` .
138+ /// Return the utf -8 string at `index` in the array. The pointer will be null if the value at `index` is null.
139+ /// The caller must free the returned pointer .
138140#[ unsafe( no_mangle) ]
139141pub unsafe extern "C-unwind" fn vx_array_get_utf8 (
140142 array : * const vx_array ,
141143 index : u32 ,
142- dst : * mut c_void ,
143- len : * mut c_int ,
144- ) {
144+ ) -> * const vx_string {
145145 let array = vx_array:: as_ref ( array) ;
146146 let value = array. scalar_at ( index as usize ) ;
147147 let utf8_scalar = value. as_utf8 ( ) ;
148148 if let Some ( buffer) = utf8_scalar. value ( ) {
149- let bytes = buffer. as_bytes ( ) ;
150- let dst = unsafe { 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 ( ) } ;
149+ vx_string:: new ( Arc :: from ( buffer. as_str ( ) ) )
150+ } else {
151+ ptr:: null ( )
153152 }
154153}
155154
156- /// Write the UTF-8 string at `index` in the array into the provided destination buffer, recording
157- /// the length in `len` .
155+ /// Return the binary at `index` in the array. The pointer will be null if the value at `index` is null.
156+ /// The caller must free the returned pointer .
158157#[ unsafe( no_mangle) ]
159158pub unsafe extern "C-unwind" fn vx_array_get_binary (
160159 array : * const vx_array ,
161160 index : u32 ,
162- dst : * mut c_void ,
163- len : * mut c_int ,
164- ) {
161+ ) -> * const vx_binary {
165162 let array = vx_array:: as_ref ( array) ;
166163 let value = array. scalar_at ( index as usize ) ;
167- let utf8_scalar = value. as_binary ( ) ;
168- if let Some ( bytes) = utf8_scalar . value ( ) {
169- let dst = unsafe { 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 ( ) } ;
164+ let binary_scalar = value. as_binary ( ) ;
165+ if let Some ( bytes) = binary_scalar . value ( ) {
166+ vx_binary :: new ( Arc :: from ( bytes. as_bytes ( ) ) )
167+ } else {
168+ ptr :: null ( )
172169 }
173170}
174171
175172#[ cfg( test) ]
176173mod tests {
177- use std:: ffi:: { c_int, c_void} ;
178174 use std:: ptr;
179175
180176 use vortex:: IntoArray ;
@@ -185,8 +181,10 @@ mod tests {
185181 use vortex:: validity:: Validity ;
186182
187183 use crate :: array:: * ;
184+ use crate :: binary:: vx_binary_free;
188185 use crate :: dtype:: { vx_dtype_get_variant, vx_dtype_variant} ;
189186 use crate :: error:: vx_error_free;
187+ use crate :: string:: vx_string_free;
190188
191189 #[ test]
192190 fn test_simple ( ) {
@@ -349,35 +347,17 @@ mod tests {
349347 let utf8_array = VarBinViewArray :: from_iter_str ( [ "hello" , "world" , "test" ] ) ;
350348 let ffi_array = vx_array:: new ( utf8_array. into_array ( ) ) ;
351349
352- let mut buffer = vec ! [ 0u8 ; 10 ] ;
353- let mut len: c_int = 0 ;
350+ let vx_str1 = vx_array_get_utf8 ( ffi_array, 0 ) ;
351+ assert_eq ! ( vx_string:: as_str( vx_str1) , "hello" ) ;
352+ vx_string_free ( vx_str1) ;
354353
355- vx_array_get_utf8 (
356- ffi_array,
357- 0 ,
358- buffer. as_mut_ptr ( ) as * mut c_void ,
359- & raw mut len,
360- ) ;
361- assert_eq ! ( len, 5 ) ;
362- assert_eq ! ( & buffer[ ..5 ] , b"hello" ) ;
363-
364- vx_array_get_utf8 (
365- ffi_array,
366- 1 ,
367- buffer. as_mut_ptr ( ) as * mut c_void ,
368- & raw mut len,
369- ) ;
370- assert_eq ! ( len, 5 ) ;
371- assert_eq ! ( & buffer[ ..5 ] , b"world" ) ;
372-
373- vx_array_get_utf8 (
374- ffi_array,
375- 2 ,
376- buffer. as_mut_ptr ( ) as * mut c_void ,
377- & raw mut len,
378- ) ;
379- assert_eq ! ( len, 4 ) ;
380- assert_eq ! ( & buffer[ ..4 ] , b"test" ) ;
354+ let vx_str2 = vx_array_get_utf8 ( ffi_array, 1 ) ;
355+ assert_eq ! ( vx_string:: as_str( vx_str2) , "world" ) ;
356+ vx_string_free ( vx_str2) ;
357+
358+ let vx_str3 = vx_array_get_utf8 ( ffi_array, 2 ) ;
359+ assert_eq ! ( vx_string:: as_str( vx_str3) , "test" ) ;
360+ vx_string_free ( vx_str3) ;
381361
382362 vx_array_free ( ffi_array) ;
383363 }
@@ -393,35 +373,17 @@ mod tests {
393373 ] ) ;
394374 let ffi_array = vx_array:: new ( binary_array. into_array ( ) ) ;
395375
396- let mut buffer = vec ! [ 0u8 ; 10 ] ;
397- let mut len: c_int = 0 ;
376+ let vx_bin1 = vx_array_get_binary ( ffi_array, 0 ) ;
377+ assert_eq ! ( vx_binary:: as_slice( vx_bin1) , & [ 0x01 , 0x02 , 0x03 ] ) ;
378+ vx_binary_free ( vx_bin1) ;
398379
399- vx_array_get_binary (
400- ffi_array,
401- 0 ,
402- buffer. as_mut_ptr ( ) as * mut c_void ,
403- & raw mut len,
404- ) ;
405- assert_eq ! ( len, 3 ) ;
406- assert_eq ! ( & buffer[ ..3 ] , & [ 0x01 , 0x02 , 0x03 ] ) ;
407-
408- vx_array_get_binary (
409- ffi_array,
410- 1 ,
411- buffer. as_mut_ptr ( ) as * mut c_void ,
412- & raw mut len,
413- ) ;
414- assert_eq ! ( len, 2 ) ;
415- assert_eq ! ( & buffer[ ..2 ] , & [ 0xFF , 0xEE ] ) ;
416-
417- vx_array_get_binary (
418- ffi_array,
419- 2 ,
420- buffer. as_mut_ptr ( ) as * mut c_void ,
421- & raw mut len,
422- ) ;
423- assert_eq ! ( len, 4 ) ;
424- assert_eq ! ( & buffer[ ..4 ] , & [ 0xAA , 0xBB , 0xCC , 0xDD ] ) ;
380+ let vx_bin2 = vx_array_get_binary ( ffi_array, 1 ) ;
381+ assert_eq ! ( vx_binary:: as_slice( vx_bin2) , & [ 0xFF , 0xEE ] ) ;
382+ vx_binary_free ( vx_bin2) ;
383+
384+ let vx_bin3 = vx_array_get_binary ( ffi_array, 2 ) ;
385+ assert_eq ! ( vx_binary:: as_slice( vx_bin3) , & [ 0xAA , 0xBB , 0xCC , 0xDD ] ) ;
386+ vx_binary_free ( vx_bin3) ;
425387
426388 vx_array_free ( ffi_array) ;
427389 }
0 commit comments