@@ -16,6 +16,9 @@ use crate::bytes::Vtable;
1616#[ allow( unused) ]
1717use crate :: loom:: sync:: atomic:: AtomicMut ;
1818use crate :: loom:: sync:: atomic:: { AtomicPtr , AtomicUsize , Ordering } ;
19+ use crate :: try_alloc:: {
20+ AllocStrategy , FallibleAllocStrategy , PanickingAllocStrategy , TryReserveError ,
21+ } ;
1922use crate :: { Buf , BufMut , Bytes , TryGetError } ;
2023
2124/// A unique reference to a contiguous slice of memory.
@@ -599,12 +602,99 @@ impl BytesMut {
599602 }
600603
601604 // will always succeed
602- let _ = self . reserve_inner ( additional, true ) ;
605+ let _ = self . reserve_inner ( additional, true , PanickingAllocStrategy ) ;
606+ }
607+
608+ /// Reserves capacity for at least `additional` more bytes to be inserted
609+ /// into the given `BytesMut`.
610+ ///
611+ /// More than `additional` bytes may be reserved in order to avoid frequent
612+ /// reallocations. A call to `reserve` may result in an allocation.
613+ ///
614+ /// Before allocating new buffer space, the function will attempt to reclaim
615+ /// space in the existing buffer. If the current handle references a view
616+ /// into a larger original buffer, and all other handles referencing part
617+ /// of the same original buffer have been dropped, then the current view
618+ /// can be copied/shifted to the front of the buffer and the handle can take
619+ /// ownership of the full buffer, provided that the full buffer is large
620+ /// enough to fit the requested additional capacity.
621+ ///
622+ /// This optimization will only happen if shifting the data from the current
623+ /// view to the front of the buffer is not too expensive in terms of the
624+ /// (amortized) time required. The precise condition is subject to change;
625+ /// as of now, the length of the data being shifted needs to be at least as
626+ /// large as the distance that it's shifted by. If the current view is empty
627+ /// and the original buffer is large enough to fit the requested additional
628+ /// capacity, then reallocations will never happen.
629+ ///
630+ /// # Examples
631+ ///
632+ /// In the following example, a new buffer is allocated.
633+ ///
634+ /// ```
635+ /// # fn main() -> Result<(), bytes::TryReserveError> {
636+ /// use bytes::BytesMut;
637+ ///
638+ /// let mut buf = BytesMut::from(&b"hello"[..]);
639+ /// buf.try_reserve(64)?;
640+ /// assert!(buf.capacity() >= 69);
641+ /// # Ok(())
642+ /// # }
643+ /// ```
644+ ///
645+ /// In the following example, the existing buffer is reclaimed.
646+ ///
647+ /// ```
648+ /// # fn main() -> Result<(), bytes::TryReserveError> {
649+ /// use bytes::{BytesMut, BufMut};
650+ ///
651+ /// let mut buf = BytesMut::with_capacity(128);
652+ /// buf.put(&[0; 64][..]);
653+ ///
654+ /// let ptr = buf.as_ptr();
655+ /// let other = buf.split();
656+ ///
657+ /// assert!(buf.is_empty());
658+ /// assert_eq!(buf.capacity(), 64);
659+ ///
660+ /// drop(other);
661+ /// buf.try_reserve(128)?;
662+ ///
663+ /// assert_eq!(buf.capacity(), 128);
664+ /// assert_eq!(buf.as_ptr(), ptr);
665+ /// # Ok(())
666+ /// # }
667+ /// ```
668+ ///
669+ /// # Errors
670+ ///
671+ /// Errors if the new capacity overflows `usize` or the underlying allocator fails.
672+ #[ inline]
673+ pub fn try_reserve ( & mut self , additional : usize ) -> Result < ( ) , TryReserveError > {
674+ let len = self . len ( ) ;
675+ let rem = self . capacity ( ) - len;
676+
677+ if additional <= rem {
678+ // The handle can already store at least `additional` more bytes, so
679+ // there is no further work needed to be done.
680+ return Ok ( ( ) ) ;
681+ }
682+
683+ self . reserve_inner ( additional, true , FallibleAllocStrategy )
684+ . map ( |_| ( ) )
603685 }
604686
605687 // In separate function to allow the short-circuits in `reserve` and `try_reclaim` to
606688 // be inline-able. Significantly helps performance. Returns false if it did not succeed.
607- fn reserve_inner ( & mut self , additional : usize , allocate : bool ) -> bool {
689+ fn reserve_inner < S > (
690+ & mut self ,
691+ additional : usize ,
692+ allocate : bool ,
693+ strategy : S ,
694+ ) -> Result < bool , S :: Err >
695+ where
696+ S : AllocStrategy ,
697+ {
608698 let len = self . len ( ) ;
609699 let kind = self . kind ( ) ;
610700
@@ -650,21 +740,21 @@ impl BytesMut {
650740 self . cap += off;
651741 } else {
652742 if !allocate {
653- return false ;
743+ return Ok ( false ) ;
654744 }
655745 // Not enough space, or reusing might be too much overhead:
656746 // allocate more space!
657747 let mut v =
658748 ManuallyDrop :: new ( rebuild_vec ( self . ptr . as_ptr ( ) , self . len , self . cap , off) ) ;
659- v . reserve ( additional) ;
749+ strategy . fallible_reserve ( & mut v , additional) ? ;
660750
661751 // Update the info
662752 self . ptr = vptr ( v. as_mut_ptr ( ) . add ( off) ) ;
663753 self . cap = v. capacity ( ) - off;
664754 debug_assert_eq ! ( self . len, v. len( ) - off) ;
665755 }
666756
667- return true ;
757+ return Ok ( true ) ;
668758 }
669759 }
670760
@@ -677,8 +767,8 @@ impl BytesMut {
677767 // Compute the new capacity
678768 let mut new_cap = match len. checked_add ( additional) {
679769 Some ( new_cap) => new_cap,
680- None if !allocate => return false ,
681- None => panic ! ( "overflow" ) ,
770+ None if !allocate => return Ok ( false ) ,
771+ None => return Err ( strategy . capacity_overflow ( ) ) ,
682772 } ;
683773
684774 unsafe {
@@ -711,7 +801,7 @@ impl BytesMut {
711801 self . cap = v. capacity ( ) ;
712802 } else {
713803 if !allocate {
714- return false ;
804+ return Ok ( false ) ;
715805 }
716806 // calculate offset
717807 let off = ( self . ptr . as_ptr ( ) as usize ) - ( v. as_ptr ( ) as usize ) ;
@@ -720,7 +810,9 @@ impl BytesMut {
720810 // `Vec`, so it does not take the offset into account.
721811 //
722812 // Thus we have to manually add it here.
723- new_cap = new_cap. checked_add ( off) . expect ( "overflow" ) ;
813+ new_cap = new_cap
814+ . checked_add ( off)
815+ . ok_or_else ( || strategy. capacity_overflow ( ) ) ?;
724816
725817 // The vector capacity is not sufficient. The reserve request is
726818 // asking for more than the initial buffer capacity. Allocate more
@@ -744,18 +836,19 @@ impl BytesMut {
744836 // care about in the unused capacity before calling `reserve`.
745837 debug_assert ! ( off + len <= v. capacity( ) ) ;
746838 v. set_len ( off + len) ;
747- v. reserve ( new_cap - v. len ( ) ) ;
839+ let additional = new_cap - v. len ( ) ;
840+ strategy. fallible_reserve ( v, additional) ?;
748841
749842 // Update the info
750843 self . ptr = vptr ( v. as_mut_ptr ( ) . add ( off) ) ;
751844 self . cap = v. capacity ( ) - off;
752845 }
753846
754- return true ;
847+ return Ok ( true ) ;
755848 }
756849 }
757850 if !allocate {
758- return false ;
851+ return Ok ( false ) ;
759852 }
760853
761854 let original_capacity_repr = unsafe { ( * shared) . original_capacity_repr } ;
@@ -779,7 +872,7 @@ impl BytesMut {
779872 self . ptr = vptr ( v. as_mut_ptr ( ) ) ;
780873 self . cap = v. capacity ( ) ;
781874 debug_assert_eq ! ( self . len, v. len( ) ) ;
782- true
875+ Ok ( true )
783876 }
784877
785878 /// Attempts to cheaply reclaim already allocated capacity for at least `additional` more
@@ -839,7 +932,10 @@ impl BytesMut {
839932 return true ;
840933 }
841934
842- self . reserve_inner ( additional, false )
935+ match self . reserve_inner ( additional, false , PanickingAllocStrategy ) {
936+ Ok ( reclaimed) => reclaimed,
937+ Err ( never) => match never { } ,
938+ }
843939 }
844940
845941 /// Appends given bytes to this `BytesMut`.
0 commit comments