@@ -597,12 +597,13 @@ impl BytesMut {
597
597
return ;
598
598
}
599
599
600
- self . reserve_inner ( additional) ;
600
+ // will always succeed
601
+ let _ = self . reserve_inner ( additional, true ) ;
601
602
}
602
603
603
- // In separate function to allow the short-circuits in `reserve` to
604
- // be inline-able. Significant helps performance.
605
- fn reserve_inner ( & mut self , additional : usize ) {
604
+ // In separate function to allow the short-circuits in `reserve` and `try_reclaim` to
605
+ // be inline-able. Significantly helps performance. Returns false if it did not succeed .
606
+ fn reserve_inner ( & mut self , additional : usize , allocate : bool ) -> bool {
606
607
let len = self . len ( ) ;
607
608
let kind = self . kind ( ) ;
608
609
@@ -647,6 +648,9 @@ impl BytesMut {
647
648
// can gain capacity back.
648
649
self . cap += off;
649
650
} else {
651
+ if !allocate {
652
+ return false ;
653
+ }
650
654
// Not enough space, or reusing might be too much overhead:
651
655
// allocate more space!
652
656
let mut v =
@@ -659,7 +663,7 @@ impl BytesMut {
659
663
debug_assert_eq ! ( self . len, v. len( ) - off) ;
660
664
}
661
665
662
- return ;
666
+ return true ;
663
667
}
664
668
}
665
669
@@ -670,7 +674,11 @@ impl BytesMut {
670
674
// allocating a new vector with the requested capacity.
671
675
//
672
676
// Compute the new capacity
673
- let mut new_cap = len. checked_add ( additional) . expect ( "overflow" ) ;
677
+ let mut new_cap = match len. checked_add ( additional) {
678
+ Some ( new_cap) => new_cap,
679
+ None if !allocate => return false ,
680
+ None => panic ! ( "overflow" ) ,
681
+ } ;
674
682
675
683
unsafe {
676
684
// First, try to reclaim the buffer. This is possible if the current
@@ -701,6 +709,9 @@ impl BytesMut {
701
709
self . ptr = vptr ( ptr) ;
702
710
self . cap = v. capacity ( ) ;
703
711
} else {
712
+ if !allocate {
713
+ return false ;
714
+ }
704
715
// calculate offset
705
716
let off = ( self . ptr . as_ptr ( ) as usize ) - ( v. as_ptr ( ) as usize ) ;
706
717
@@ -739,9 +750,12 @@ impl BytesMut {
739
750
self . cap = v. capacity ( ) - off;
740
751
}
741
752
742
- return ;
753
+ return true ;
743
754
}
744
755
}
756
+ if !allocate {
757
+ return false ;
758
+ }
745
759
746
760
let original_capacity_repr = unsafe { ( * shared) . original_capacity_repr } ;
747
761
let original_capacity = original_capacity_from_repr ( original_capacity_repr) ;
@@ -764,6 +778,67 @@ impl BytesMut {
764
778
self . ptr = vptr ( v. as_mut_ptr ( ) ) ;
765
779
self . cap = v. capacity ( ) ;
766
780
debug_assert_eq ! ( self . len, v. len( ) ) ;
781
+ return true ;
782
+ }
783
+
784
+ /// Attempts to cheaply reclaim already allocated capacity for at least `additional` more
785
+ /// bytes to be inserted into the given `BytesMut` and returns `true` if it succeeded.
786
+ ///
787
+ /// `try_reclaim` behaves exactly like `reserve`, except that it never allocates new storage
788
+ /// and returns a `bool` indicating whether it was successful in doing so:
789
+ ///
790
+ /// `try_reclaim` returns false under these conditions:
791
+ /// - The spare capacity left is less than `additional` bytes AND
792
+ /// - The existing allocation cannot be reclaimed cheaply or it was less than
793
+ /// `additional` bytes in size
794
+ ///
795
+ /// Reclaiming the allocation cheaply is possible if the `BytesMut` has no outstanding
796
+ /// references through other `BytesMut`s or `Bytes` which point to the same underlying
797
+ /// storage.
798
+ ///
799
+ /// # Examples
800
+ ///
801
+ /// ```
802
+ /// use bytes::BytesMut;
803
+ ///
804
+ /// let mut buf = BytesMut::with_capacity(64);
805
+ /// assert_eq!(true, buf.try_reclaim(64));
806
+ /// assert_eq!(64, buf.capacity());
807
+ ///
808
+ /// buf.extend_from_slice(b"abcd");
809
+ /// let mut split = buf.split();
810
+ /// assert_eq!(60, buf.capacity());
811
+ /// assert_eq!(4, split.capacity());
812
+ /// assert_eq!(false, split.try_reclaim(64));
813
+ /// assert_eq!(false, buf.try_reclaim(64));
814
+ /// // The split buffer is filled with "abcd"
815
+ /// assert_eq!(false, split.try_reclaim(4));
816
+ /// // buf is empty and has capacity for 60 bytes
817
+ /// assert_eq!(true, buf.try_reclaim(60));
818
+ ///
819
+ /// drop(buf);
820
+ /// assert_eq!(false, split.try_reclaim(64));
821
+ ///
822
+ /// split.clear();
823
+ /// assert_eq!(4, split.capacity());
824
+ /// assert_eq!(true, split.try_reclaim(64));
825
+ /// assert_eq!(64, split.capacity());
826
+ /// ```
827
+ // I tried splitting out try_reclaim_inner after the short circuits, but it was inlined
828
+ // regardless with Rust 1.78.0 so probably not worth it
829
+ #[ inline]
830
+ #[ must_use = "consider BytesMut::reserve if you need an infallible reservation" ]
831
+ pub fn try_reclaim ( & mut self , additional : usize ) -> bool {
832
+ let len = self . len ( ) ;
833
+ let rem = self . capacity ( ) - len;
834
+
835
+ if additional <= rem {
836
+ // The handle can already store at least `additional` more bytes, so
837
+ // there is no further work needed to be done.
838
+ return true ;
839
+ }
840
+
841
+ self . reserve_inner ( additional, false )
767
842
}
768
843
769
844
/// Appends given bytes to this `BytesMut`.
0 commit comments