@@ -11,6 +11,7 @@ use alloc::{
1111 vec,
1212 vec:: Vec ,
1313} ;
14+ use std:: num:: NonZeroUsize ;
1415
1516use crate :: buf:: { IntoIter , UninitSlice } ;
1617use crate :: bytes:: Vtable ;
@@ -819,6 +820,70 @@ impl BytesMut {
819820 }
820821 }
821822
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+
822887 // private
823888
824889 // For now, use a `Vec` to manage the memory for us, but we may want to
0 commit comments