@@ -11,6 +11,7 @@ use alloc::{
11
11
vec,
12
12
vec:: Vec ,
13
13
} ;
14
+ use std:: num:: NonZeroUsize ;
14
15
15
16
use crate :: buf:: { IntoIter , UninitSlice } ;
16
17
use crate :: bytes:: Vtable ;
@@ -819,6 +820,70 @@ impl BytesMut {
819
820
}
820
821
}
821
822
823
+ /// Attempts to reclaim the whole allocation of the `BytesMut`.
824
+ ///
825
+ /// If the `BytesMut` is empty but the underlying storage has been used before,
826
+ /// it might be possible to cheaply reclaim space by just updating a few indices.
827
+ /// Returns `None` if the `BytesMut` is not empty, there is nothing to reclaim
828
+ /// (no underlying storage has been allocated), or there are any other live
829
+ /// references to the underlying storage. Otherwise, returns the available
830
+ /// capacity after reclaiming.
831
+ ///
832
+ /// # Examples
833
+ ///
834
+ /// ```
835
+ /// use bytes::BytesMut;
836
+ /// use core::num::NonZeroUsize;
837
+ ///
838
+ /// let mut buf = BytesMut::with_capacity(64);
839
+ /// assert_eq!(None, buf.try_reclaim());
840
+ ///
841
+ /// buf.extend_from_slice(b"abcd");
842
+ /// let mut split = buf.split();
843
+ /// assert_eq!(None, split.try_reclaim());
844
+ /// assert_eq!(None, buf.try_reclaim());
845
+ /// drop(buf);
846
+ /// assert_eq!(None, split.try_reclaim());
847
+ /// split.clear();
848
+ /// assert_eq!(Some(64), split.try_reclaim().map(NonZeroUsize::into));
849
+ /// ```
850
+ pub fn try_reclaim ( & mut self ) -> Option < NonZeroUsize > {
851
+ if !self . is_empty ( ) {
852
+ return None
853
+ }
854
+
855
+ let kind = self . kind ( ) ;
856
+ if kind == KIND_VEC {
857
+ unsafe {
858
+ let off = self . get_vec_pos ( ) ;
859
+ if off == 0 {
860
+ return None
861
+ }
862
+
863
+ let base_ptr = self . ptr . as_ptr ( ) . sub ( off) ;
864
+ self . ptr = vptr ( base_ptr) ;
865
+ self . set_vec_pos ( 0 ) ;
866
+ self . cap += off;
867
+ debug_assert ! ( self . capacity( ) > 0 ) ;
868
+ return Some ( NonZeroUsize :: new_unchecked ( self . capacity ( ) ) )
869
+ }
870
+ }
871
+ let shared: * mut Shared = self . data ;
872
+
873
+ unsafe {
874
+ if !( * shared) . is_unique ( ) {
875
+ return None
876
+ }
877
+ let v = & mut ( * shared) . vec ;
878
+
879
+ let ptr = v. as_mut_ptr ( ) ;
880
+ self . ptr = vptr ( ptr) ;
881
+ self . cap = v. capacity ( ) ;
882
+ debug_assert ! ( self . capacity( ) > 0 ) ;
883
+ Some ( NonZeroUsize :: new_unchecked ( self . capacity ( ) ) )
884
+ }
885
+ }
886
+
822
887
// private
823
888
824
889
// For now, use a `Vec` to manage the memory for us, but we may want to
0 commit comments