44use std:: ffi:: { CStr , CString , c_void} ;
55use std:: ptr;
66
7- use arrow_buffer;
8- use arrow_buffer:: Buffer ;
97use bitvec:: macros:: internal:: funty:: Fundamental ;
108use bitvec:: slice:: BitSlice ;
119use bitvec:: view:: BitView ;
10+ use vortex:: buffer:: { BitBuffer , Buffer } ;
1211use vortex:: error:: { VortexResult , VortexUnwrap , vortex_bail, vortex_err} ;
12+ use vortex:: validity:: Validity ;
1313
1414use crate :: cpp:: { duckdb_vx_error, idx_t} ;
1515use crate :: duckdb:: vector_buffer:: VectorBuffer ;
@@ -302,20 +302,17 @@ impl ValidityRef<'_> {
302302 ( validity_entry & ( 1u64 << idx_in_entry) ) != 0
303303 }
304304
305- /// Creates a NullBuffer directly from the DuckDB validity mask for optimal performance.
306- ///
307- /// Returns None if all values are valid (no null buffer needed).
308- pub fn to_null_buffer ( & self ) -> Option < arrow_buffer:: NullBuffer > {
305+ /// Creates a Validity directly from the DuckDB validity mask for optimal performance.
306+ pub fn to_validity ( & self ) -> Validity {
309307 let Some ( validity) = self . validity else {
310- // All values are valid - no null buffer needed
311- return None ;
308+ // All values are valid
309+ return Validity :: AllValid ;
312310 } ;
313311
314- // Create copy of the buffer from the DuckDB validity mask.
315- let buffer = Buffer :: from_iter ( validity. iter ( ) . cloned ( ) ) ;
316-
317- let boolean_buffer = arrow_buffer:: BooleanBuffer :: new ( buffer, 0 , self . len ) ;
318- Some ( arrow_buffer:: NullBuffer :: new ( boolean_buffer) )
312+ Validity :: from ( BitBuffer :: new (
313+ Buffer :: < u64 > :: copy_from ( validity) . into_byte_buffer ( ) ,
314+ self . len ,
315+ ) )
319316 }
320317}
321318
@@ -325,19 +322,23 @@ mod tests {
325322 use crate :: cpp:: DUCKDB_TYPE ;
326323
327324 #[ test]
328- fn test_create_null_buffer_all_valid ( ) {
325+ fn test_create_validity_all_valid ( ) {
329326 // Test case where all values are valid - should return None
330327 let len = 10 ;
331328 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
332329 let vector = Vector :: with_capacity ( logical_type, len) ;
333330
334331 let validity = vector. validity_ref ( len) ;
335- let null_buffer = validity. to_null_buffer ( ) ;
336- assert ! ( null_buffer. is_none( ) , "Expected None for all-valid vector" ) ;
332+ let validity = validity. to_validity ( ) ;
333+ assert_eq ! (
334+ validity,
335+ Validity :: AllValid ,
336+ "Expected None for all-valid vector"
337+ ) ;
337338 }
338339
339340 #[ test]
340- fn test_create_null_buffer_with_nulls ( ) {
341+ fn test_create_validity_with_nulls ( ) {
341342 // Test case with some null values
342343 let len = 10 ;
343344 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
@@ -351,30 +352,24 @@ mod tests {
351352 validity_slice. set ( 7 , false ) ; // null at position 7
352353
353354 let validity = vector. validity_ref ( len) ;
354- let null_buffer = validity. to_null_buffer ( ) ;
355- assert ! (
356- null_buffer. is_some( ) ,
357- "Expected Some(NullBuffer) for vector with nulls"
358- ) ;
359-
360- let null_buffer = null_buffer. unwrap ( ) ;
361- assert_eq ! ( null_buffer. len( ) , len) ;
355+ let validity = validity. to_validity ( ) ;
356+ assert_eq ! ( validity. maybe_len( ) , Some ( len) ) ;
362357
363358 // Check that the right positions are null
364- assert ! ( null_buffer . is_valid( 0 ) ) ;
365- assert ! ( null_buffer . is_null( 1 ) ) ;
366- assert ! ( null_buffer . is_valid( 2 ) ) ;
367- assert ! ( null_buffer . is_null( 3 ) ) ;
368- assert ! ( null_buffer . is_valid( 4 ) ) ;
369- assert ! ( null_buffer . is_valid( 5 ) ) ;
370- assert ! ( null_buffer . is_valid( 6 ) ) ;
371- assert ! ( null_buffer . is_null( 7 ) ) ;
372- assert ! ( null_buffer . is_valid( 8 ) ) ;
373- assert ! ( null_buffer . is_valid( 9 ) ) ;
359+ assert ! ( validity . is_valid( 0 ) ) ;
360+ assert ! ( validity . is_null( 1 ) ) ;
361+ assert ! ( validity . is_valid( 2 ) ) ;
362+ assert ! ( validity . is_null( 3 ) ) ;
363+ assert ! ( validity . is_valid( 4 ) ) ;
364+ assert ! ( validity . is_valid( 5 ) ) ;
365+ assert ! ( validity . is_valid( 6 ) ) ;
366+ assert ! ( validity . is_null( 7 ) ) ;
367+ assert ! ( validity . is_valid( 8 ) ) ;
368+ assert ! ( validity . is_valid( 9 ) ) ;
374369 }
375370
376371 #[ test]
377- fn test_create_null_buffer_single_element ( ) {
372+ fn test_create_validity_single_element ( ) {
378373 // Test with a single element that is null
379374 let len = 1 ;
380375 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
@@ -385,16 +380,13 @@ mod tests {
385380 validity_slice. set ( 0 , false ) ; // null at position 0
386381
387382 let validity = vector. validity_ref ( len) ;
388- let null_buffer = validity. to_null_buffer ( ) ;
389- assert ! ( null_buffer. is_some( ) ) ;
390-
391- let null_buffer = null_buffer. unwrap ( ) ;
392- assert_eq ! ( null_buffer. len( ) , 1 ) ;
393- assert ! ( null_buffer. is_null( 0 ) ) ;
383+ let validity = validity. to_validity ( ) ;
384+ assert_eq ! ( validity. maybe_len( ) , Some ( 1 ) ) ;
385+ assert ! ( validity. is_null( 0 ) ) ;
394386 }
395387
396388 #[ test]
397- fn test_create_null_buffer_single_element_valid ( ) {
389+ fn test_create_validity_single_element_valid ( ) {
398390 // Test with a single valid element
399391 let len = 1 ;
400392 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
@@ -405,29 +397,26 @@ mod tests {
405397 let _validity_slice = unsafe { vector. ensure_validity_bitslice ( len) } ;
406398
407399 let validity = vector. validity_ref ( len) ;
408- let null_buffer = validity. to_null_buffer ( ) ;
409- assert ! ( null_buffer. is_some( ) ) ;
410-
411- let null_buffer = null_buffer. unwrap ( ) ;
412- assert_eq ! ( null_buffer. len( ) , 1 ) ;
413- assert ! ( null_buffer. is_valid( 0 ) ) ;
400+ let validity = validity. to_validity ( ) ;
401+ assert_eq ! ( validity. maybe_len( ) , Some ( 1 ) ) ;
402+ assert ! ( validity. is_valid( 0 ) ) ;
414403 }
415404
416405 #[ test]
417- fn test_create_null_buffer_empty ( ) {
406+ fn test_create_validity_empty ( ) {
418407 // Test with zero length
419408 let len = 0 ;
420409 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
421410 let vector = Vector :: with_capacity ( logical_type, len) ;
422411
423412 let validity = vector. validity_ref ( len) ;
424- let null_buffer = validity. to_null_buffer ( ) ;
413+ let validity = validity. to_validity ( ) ;
425414 // Even with zero length, if validity mask doesn't exist, should return None
426- assert ! ( null_buffer . is_none ( ) ) ;
415+ assert_eq ! ( validity , Validity :: AllValid ) ;
427416 }
428417
429418 #[ test]
430- fn test_create_null_buffer_all_nulls ( ) {
419+ fn test_create_validity_all_nulls ( ) {
431420 // Test case where all values are null
432421 let len = 10 ;
433422 let logical_type = LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_INTEGER ) ;
@@ -441,16 +430,10 @@ mod tests {
441430 }
442431
443432 let validity = vector. validity_ref ( len) ;
444- let null_buffer = validity. to_null_buffer ( ) ;
445- assert ! ( null_buffer. is_some( ) ) ;
446-
447- let null_buffer = null_buffer. unwrap ( ) ;
448- assert_eq ! ( null_buffer. len( ) , len) ;
449-
433+ let validity = validity. to_validity ( ) ;
434+ assert_eq ! ( validity. maybe_len( ) , Some ( len) ) ;
450435 // Check that all positions are null
451- for i in 0 ..len {
452- assert ! ( null_buffer. is_null( i) , "Element {i} should be null" ) ;
453- }
436+ assert_eq ! ( validity, Validity :: AllInvalid ) ;
454437 }
455438
456439 #[ test]
0 commit comments