@@ -22,6 +22,7 @@ use crate::arrays::VarBin;
2222use crate :: arrays:: VarBinArray ;
2323use crate :: arrays:: dict:: TakeExecute ;
2424use crate :: arrays:: piecewise_sequence:: constant_unsigned_usize;
25+ use crate :: arrays:: piecewise_sequence:: copy_slice_to_spare;
2526use crate :: arrays:: piecewise_sequence:: maybe_contiguous_slices;
2627use crate :: arrays:: primitive:: PrimitiveArrayExt ;
2728use crate :: arrays:: varbin:: VarBinArrayExt ;
@@ -474,6 +475,7 @@ where
474475 }
475476
476477 let mut new_data = ByteBufferMut :: with_capacity ( output_bytes) ;
478+ let mut cursor = 0usize ;
477479 for & start in starts {
478480 let start = start. as_ ( ) ;
479481 if length == 0 {
@@ -483,8 +485,20 @@ where
483485 let offset_range = & offsets[ start..] [ ..=length] ;
484486 let byte_start = offset_range[ 0 ] . as_ ( ) ;
485487 let byte_end = offset_range[ length] . as_ ( ) ;
486- new_data. extend_from_slice ( & data[ byte_start..] [ ..byte_end - byte_start] ) ;
488+ cursor = copy_slice_to_spare (
489+ & mut new_data,
490+ cursor,
491+ & data[ byte_start..] [ ..byte_end - byte_start] ,
492+ output_bytes,
493+ ) ?;
487494 }
495+ vortex_ensure ! (
496+ cursor == output_bytes,
497+ "VarBin byte copy length {cursor} does not match computed byte length {output_bytes}"
498+ ) ;
499+ // SAFETY: `copy_slice_to_spare` checked every write against `output_bytes`, and `cursor ==
500+ // output_bytes` proves all bytes were initialized.
501+ unsafe { new_data. set_len ( output_bytes) } ;
488502
489503 let offsets = PrimitiveArray :: new ( new_offsets. freeze ( ) , Validity :: NonNullable )
490504 . reinterpret_cast ( out_offset_ptype)
@@ -551,6 +565,7 @@ where
551565 ) ;
552566
553567 let mut new_data = ByteBufferMut :: with_capacity ( output_bytes) ;
568+ let mut cursor = 0usize ;
554569 for ( & start, & length) in starts. iter ( ) . zip_eq ( lengths) {
555570 let start = start. as_ ( ) ;
556571 let length = length. as_ ( ) ;
@@ -561,8 +576,20 @@ where
561576 let offset_range = & offsets[ start..] [ ..=length] ;
562577 let byte_start = offset_range[ 0 ] . as_ ( ) ;
563578 let byte_end = offset_range[ length] . as_ ( ) ;
564- new_data. extend_from_slice ( & data[ byte_start..] [ ..byte_end - byte_start] ) ;
579+ cursor = copy_slice_to_spare (
580+ & mut new_data,
581+ cursor,
582+ & data[ byte_start..] [ ..byte_end - byte_start] ,
583+ output_bytes,
584+ ) ?;
565585 }
586+ vortex_ensure ! (
587+ cursor == output_bytes,
588+ "VarBin byte copy length {cursor} does not match computed byte length {output_bytes}"
589+ ) ;
590+ // SAFETY: `copy_slice_to_spare` checked every write against `output_bytes`, and `cursor ==
591+ // output_bytes` proves all bytes were initialized.
592+ unsafe { new_data. set_len ( output_bytes) } ;
566593
567594 let offsets = PrimitiveArray :: new ( new_offsets. freeze ( ) , Validity :: NonNullable )
568595 . reinterpret_cast ( out_offset_ptype)
0 commit comments