@@ -827,15 +827,18 @@ impl BytesMut {
827827 }
828828 }
829829
830- /// Attempts to reclaim the whole allocation of the `BytesMut`.
830+ /// Attempts to cheaply reclaim the whole allocation of the `BytesMut`.
831831 ///
832- /// If the `BytesMut` is empty but the underlying storage has been used before,
833- /// it might be possible to cheaply reclaim capacity as long as there are no
834- /// other `Bytes` or `BytesMut` handles alive .
832+ /// If no other `Bytes` or `BytesMut` handles to the underlying storage of this
833+ /// `BytesMut` are alive, it might be possible to cheaply reclaim the full capacity
834+ /// of the allocation .
835835 ///
836- /// Returns `true` if the allocation was reclaimed (or reclaiming was not
837- /// necessary, because the underlying storage was empty); returns `false` if the
838- /// `BytesMut` is not empty or there are other outstanding references to the
836+ /// `try_reclaim` never copies bytes internally, therefore it always returns `false`
837+ /// if the `BytesMut` is not empty.
838+ ///
839+ /// Returns `true` if the allocation was reclaimed (or reclaiming was not necessary,
840+ /// because the underlying storage was already fully available); returns `false` if the
841+ /// `BytesMut` is not empty or there are other outstanding handles to the
839842 /// underlying storage.
840843 ///
841844 /// # Examples
@@ -845,15 +848,22 @@ impl BytesMut {
845848 ///
846849 /// let mut buf = BytesMut::with_capacity(64);
847850 /// assert_eq!(true, buf.try_reclaim());
851+ /// assert_eq!(64, buf.capacity());
848852 ///
849853 /// buf.extend_from_slice(b"abcd");
850854 /// let mut split = buf.split();
855+ /// assert_eq!(60, buf.capacity());
856+ /// assert_eq!(4, split.capacity());
851857 /// assert_eq!(false, split.try_reclaim());
852858 /// assert_eq!(false, buf.try_reclaim());
859+ ///
853860 /// drop(buf);
854861 /// assert_eq!(false, split.try_reclaim());
862+ ///
855863 /// split.clear();
864+ /// assert_eq!(4, split.capacity());
856865 /// assert_eq!(true, split.try_reclaim());
866+ /// assert_eq!(64, split.capacity());
857867 /// ```
858868 #[ must_use = "consider BytesMut::reserve if you need a specific capacity" ]
859869 pub fn try_reclaim ( & mut self ) -> bool {
@@ -863,41 +873,54 @@ impl BytesMut {
863873
864874 let kind = self . kind ( ) ;
865875 if kind == KIND_VEC {
866- unsafe {
867- // Short-circuit if we are already at the start of the vector.
868- let off = self . get_vec_pos ( ) ;
869- if off == 0 {
870- return true ;
871- }
872- // Otherwise, update info to point at the front of the vector
873- // again and reclaim capacity
874- let base_ptr = self . ptr . as_ptr ( ) . sub ( off) ;
875- self . ptr = vptr ( base_ptr) ;
876- self . set_vec_pos ( 0 ) ;
877- self . cap += off;
876+ // Safety: self is of KIND_VEC, so calling get_vec_pos() is safe.
877+ let off = unsafe { self . get_vec_pos ( ) } ;
878+
879+ // Short-circuit if we are already at the start of the vector.
880+ if off == 0 {
878881 return true ;
879882 }
883+ // Otherwise, update info to point at the front of the vector
884+ // again and reclaim capacity
885+ //
886+ // Safety: Offset `off` means self.ptr was moved `off` bytes from the base
887+ // pointer of the allocation. Going back to the base pointer stays within
888+ // that same allocation.
889+ let base_ptr = unsafe { self . ptr . as_ptr ( ) . sub ( off) } ;
890+ self . ptr = vptr ( base_ptr) ;
891+
892+ // Safety: Resetting the offset to 0 is safe as we reset the storage
893+ // pointer to the base pointer of the allocation above
894+ unsafe { self . set_vec_pos ( 0 ) }
895+ self . cap += off;
896+
897+ return true ;
880898 }
899+
900+ debug_assert_eq ! ( kind, KIND_ARC ) ;
881901 let shared: * mut Shared = self . data ;
882902
883- unsafe {
884- // If there are other references to the underlying storage, we cannot reclaim
885- if !( * shared) . is_unique ( ) {
886- return false ;
887- }
888- let v = & mut ( * shared) . vec ;
889- let cap = v. capacity ( ) ;
890- if cap == 0 {
891- // Short-circuit as an empty vector is trivially reclaimed already
892- return true ;
893- }
903+ // If there are other references to the underlying storage, we cannot reclaim
904+ //
905+ // Safety: self is of type KIND_ARC, so the Shared ptr is valid
906+ if unsafe { !( * shared) . is_unique ( ) } {
907+ return false ;
908+ }
894909
895- // Update info to point at start of allocation and reclaim capacity
896- let ptr = v. as_mut_ptr ( ) ;
897- self . ptr = vptr ( ptr) ;
898- self . cap = cap;
899- true
910+ // Safety: self is of type KIND_ARC and there are no other handles alive, so we
911+ // can get a mut reference to the underlying storage
912+ let v = unsafe { & mut ( * shared) . vec } ;
913+ let cap = v. capacity ( ) ;
914+ if cap == 0 {
915+ // Short-circuit as an empty vector is trivially reclaimed already
916+ return true ;
900917 }
918+
919+ // Update info to point at start of allocation and reclaim capacity
920+ let ptr = v. as_mut_ptr ( ) ;
921+ self . ptr = vptr ( ptr) ;
922+ self . cap = cap;
923+ true
901924 }
902925
903926 // private
0 commit comments