@@ -675,13 +675,20 @@ impl ByteViewArrayDecoderDelta {
675675 // <https://parquet.apache.org/docs/file-format/data-pages/encodings/#delta-strings-delta_byte_array--7>
676676
677677 fn read ( & mut self , output : & mut ViewBuffer , len : usize ) -> Result < usize > {
678- output. views . reserve ( len. min ( self . decoder . remaining ( ) ) ) ;
678+ let to_reserve = len. min ( self . decoder . remaining ( ) ) ;
679+ output. views . reserve ( to_reserve) ;
679680
680681 // array buffer only have long strings
681682 let mut array_buffer: Vec < u8 > = Vec :: with_capacity ( 4096 ) ;
682683
683684 let buffer_id = output. buffers . len ( ) as u32 ;
684685
686+ // Use unsafe ptr writes instead of per-element push to avoid
687+ // repeated length checks. Safety: we reserved enough space above.
688+ let views_ptr = output. views . as_mut_ptr ( ) ;
689+ let initial_len = output. views . len ( ) ;
690+ let mut write_count = 0 ;
691+
685692 let read = if !self . validate_utf8 {
686693 self . decoder . read ( len, |bytes| {
687694 let offset = array_buffer. len ( ) ;
@@ -691,18 +698,18 @@ impl ByteViewArrayDecoderDelta {
691698 array_buffer. extend_from_slice ( bytes) ;
692699 }
693700
694- // # Safety
695- // The buffer_id is the last buffer in the output buffers
696- // The offset is calculated from the buffer, so it is valid
701+ // Safety: views_ptr is valid for writes, we reserved enough space,
702+ // and write_count < to_reserve.
697703 unsafe {
698- output . append_raw_view_unchecked ( view) ;
704+ views_ptr . add ( initial_len + write_count ) . write ( view) ;
699705 }
706+ write_count += 1 ;
700707 Ok ( ( ) )
701708 } ) ?
702709 } else {
703710 // utf8 validation buffer has only short strings. These short
704711 // strings are inlined into the views but we copy them into a
705- // contiguous buffer to accelerate validation.®
712+ // contiguous buffer to accelerate validation.
706713 let mut utf8_validation_buffer = Vec :: with_capacity ( 4096 ) ;
707714
708715 let v = self . decoder . read ( len, |bytes| {
@@ -715,20 +722,24 @@ impl ByteViewArrayDecoderDelta {
715722 utf8_validation_buffer. extend_from_slice ( bytes) ;
716723 }
717724
718- // # Safety
719- // The buffer_id is the last buffer in the output buffers
720- // The offset is calculated from the buffer, so it is valid
721- // Utf-8 validation is done later
725+ // Safety: views_ptr is valid for writes, we reserved enough space,
726+ // and write_count < to_reserve. Utf-8 validation is done later.
722727 unsafe {
723- output . append_raw_view_unchecked ( view) ;
728+ views_ptr . add ( initial_len + write_count ) . write ( view) ;
724729 }
730+ write_count += 1 ;
725731 Ok ( ( ) )
726732 } ) ?;
727733 check_valid_utf8 ( & array_buffer) ?;
728734 check_valid_utf8 ( & utf8_validation_buffer) ?;
729735 v
730736 } ;
731737
738+ // Safety: we wrote exactly `read` views via ptr writes above
739+ unsafe {
740+ output. views . set_len ( initial_len + read) ;
741+ }
742+
732743 let actual_block_id = output. append_block ( Buffer :: from_vec ( array_buffer) ) ;
733744 assert_eq ! ( actual_block_id, buffer_id) ;
734745 Ok ( read)
0 commit comments