@@ -543,8 +543,42 @@ impl MutableBuffer {
543543 iterator. for_each ( |item| self . push ( item) ) ;
544544 }
545545
546+ /// Extends a [`MutableBuffer`] from an [`Iterator`] with a trusted (upper) length.
547+ ///
548+ /// See [`MutableBuffer::from_trusted_len_iter`] for more details.
549+ ///
550+ /// # Safety
551+ /// This method assumes that the iterator's size is correct and is undefined
552+ /// behavior to use it on an iterator that reports an incorrect length.
553+ #[ inline]
554+ pub unsafe fn extend_from_trusted_len_iter < T : ArrowNativeType , I : Iterator < Item = T > > (
555+ & mut self ,
556+ iterator : I ,
557+ ) {
558+ let item_size = std:: mem:: size_of :: < T > ( ) ;
559+ let ( lower, _) = iterator. size_hint ( ) ;
560+ let additional = lower * item_size;
561+ self . reserve ( additional) ;
562+
563+ // this is necessary because of https://github.com/rust-lang/rust/issues/32155
564+ let mut dst = unsafe { self . data . as_ptr ( ) . add ( self . len ) } ;
565+ for item in iterator {
566+ // note how there is no reserve here (compared with `extend_from_iter`)
567+ let src = item. to_byte_slice ( ) . as_ptr ( ) ;
568+ std:: ptr:: copy_nonoverlapping ( src, dst, item_size) ;
569+ dst = dst. add ( item_size) ;
570+ }
571+ self . len += additional;
572+ assert_eq ! (
573+ dst. offset_from( self . data. as_ptr( ) ) as usize ,
574+ self . len,
575+ "Trusted iterator length was not accurately reported"
576+ ) ;
577+ }
578+
546579 /// Creates a [`MutableBuffer`] from an [`Iterator`] with a trusted (upper) length.
547- /// Prefer this to `collect` whenever possible, as it is faster ~60% faster.
580+ /// Prefer this to `collect` whenever possible, as it is ~60% faster.
581+ ///
548582 /// # Example
549583 /// ```
550584 /// # use arrow_buffer::buffer::MutableBuffer;
@@ -554,16 +588,18 @@ impl MutableBuffer {
554588 /// assert_eq!(buffer.len(), 4) // u32 has 4 bytes
555589 /// ```
556590 /// # Safety
557- /// This method assumes that the iterator's size is correct and is undefined behavior
558- /// to use it on an iterator that reports an incorrect length.
559- // This implementation is required for two reasons:
560- // 1. there is no trait `TrustedLen` in stable rust and therefore
561- // we can't specialize `extend` for `TrustedLen` like `Vec` does.
562- // 2. `from_trusted_len_iter` is faster.
591+ /// This method assumes that the iterator's size is correct and is undefined
592+ /// behavior to use it on an iterator that reports an incorrect length.
593+ ///
594+ /// This implementation is required for two reasons:
595+ /// 1. there is no trait `TrustedLen` in stable Rust and therefore
596+ /// we can't specialize `extend` for `TrustedLen` like `Vec` does.
597+ /// 2. `from_trusted_len_iter` is faster.
563598 #[ inline]
564599 pub unsafe fn from_trusted_len_iter < T : ArrowNativeType , I : Iterator < Item = T > > (
565600 iterator : I ,
566601 ) -> Self {
602+ // TODO: reduce duplication with `extend_from_trusted_len_iter`
567603 let item_size = std:: mem:: size_of :: < T > ( ) ;
568604 let ( _, upper) = iterator. size_hint ( ) ;
569605 let upper = upper. expect ( "from_trusted_len_iter requires an upper limit" ) ;
0 commit comments