@@ -946,6 +946,55 @@ impl<'a, T: Trace + ?Sized, U: ?Sized> GcCellRefMut<'a, T, U> {
946
946
value : f ( value) ,
947
947
}
948
948
}
949
+
950
+ /// Makes a new `GcCellRefMut` for an optional component of the borrowed
951
+ /// data. The original guard is returned as an `Err(..)` if the closure
952
+ /// returns `None`.
953
+ ///
954
+ /// The `GcCellRefMut` is already mutably borrowed, so this cannot fail.
955
+ ///
956
+ /// This is an associated function that needs to be used as
957
+ /// `GcCellRefMut::filter_map(...)`. A method would interfere with methods
958
+ /// of the same name on the contents of a `GcCell` used through `Deref`.
959
+ ///
960
+ /// # Examples
961
+ ///
962
+ /// ```
963
+ /// use gc::{GcCell, GcCellRefMut};
964
+ ///
965
+ /// let c = GcCell::new(vec![1, 2, 3]);
966
+ ///
967
+ /// {
968
+ /// let b1: GcCellRefMut<Vec<u32>> = c.borrow_mut();
969
+ /// let mut b2: Result<GcCellRefMut<Vec<u32>, u32>, _> = GcCellRefMut::filter_map(b1, |v| v.get_mut(1));
970
+ ///
971
+ /// if let Ok(mut b2) = b2 {
972
+ /// *b2 += 2;
973
+ /// }
974
+ /// }
975
+ ///
976
+ /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
977
+ /// ```
978
+ #[ inline]
979
+ pub fn filter_map < V , F > ( orig : Self , f : F ) -> Result < GcCellRefMut < ' a , T , V > , Self >
980
+ where
981
+ V : ?Sized ,
982
+ F : FnOnce ( & mut U ) -> Option < & mut V > ,
983
+ {
984
+ let gc_cell = orig. gc_cell ;
985
+
986
+ // Use MaybeUninit to avoid calling the destructor of
987
+ // GcCellRefMut (which would update the borrow flags) and to
988
+ // avoid duplicating the mutable reference orig.value (which
989
+ // would be UB).
990
+ let orig = mem:: MaybeUninit :: new ( orig) ;
991
+ let value = unsafe { ptr:: addr_of!( ( * orig. as_ptr( ) ) . value) . read ( ) } ;
992
+
993
+ match f ( value) {
994
+ None => Err ( unsafe { orig. assume_init ( ) } ) ,
995
+ Some ( value) => Ok ( GcCellRefMut { gc_cell, value } ) ,
996
+ }
997
+ }
949
998
}
950
999
951
1000
impl < ' a , T : Trace + ?Sized , U : ?Sized > Deref for GcCellRefMut < ' a , T , U > {
0 commit comments