@@ -1573,6 +1573,47 @@ impl<'b, T: ?Sized> Ref<'b, T> {
15731573 }
15741574 }
15751575
1576+ /// Tries to makes a new `Ref` for a component of the borrowed data.
1577+ /// On failure, the original guard is returned alongside with the error
1578+ /// returned by the closure.
1579+ ///
1580+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
1581+ ///
1582+ /// This is an associated function that needs to be used as
1583+ /// `Ref::try_map(...)`. A method would interfere with methods of the same
1584+ /// name on the contents of a `RefCell` used through `Deref`.
1585+ ///
1586+ /// # Examples
1587+ ///
1588+ /// ```
1589+ /// #![feature(refcell_try_map)]
1590+ /// use std::cell::{RefCell, Ref};
1591+ /// use std::str::{from_utf8, Utf8Error};
1592+ ///
1593+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6 ,0x80]);
1594+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1595+ /// let b2: Result<Ref<'_, str>, _> = Ref::try_map(b1, |v| from_utf8(v));
1596+ /// assert_eq!(&*b2.unwrap(), "🦀");
1597+ ///
1598+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6]);
1599+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1600+ /// let b2: Result<_, (Ref<'_, Vec<u8>>, Utf8Error)> = Ref::try_map(b1, |v| from_utf8(v));
1601+ /// let (b3, e) = b2.unwrap_err();
1602+ /// assert_eq!(*b3, vec![0xF0, 0x9F, 0xA6]);
1603+ /// assert_eq!(e.valid_up_to(), 0);
1604+ /// ```
1605+ #[ unstable( feature = "refcell_try_map" , issue = "143801" ) ]
1606+ #[ inline]
1607+ pub fn try_map < U : ?Sized , E > (
1608+ orig : Ref < ' b , T > ,
1609+ f : impl FnOnce ( & T ) -> Result < & U , E > ,
1610+ ) -> Result < Ref < ' b , U > , ( Self , E ) > {
1611+ match f ( & * orig) {
1612+ Ok ( value) => Ok ( Ref { value : NonNull :: from ( value) , borrow : orig. borrow } ) ,
1613+ Err ( e) => Err ( ( orig, e) ) ,
1614+ }
1615+ }
1616+
15761617 /// Splits a `Ref` into multiple `Ref`s for different components of the
15771618 /// borrowed data.
15781619 ///
@@ -1734,6 +1775,58 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
17341775 }
17351776 }
17361777
1778+ /// Tries to makes a new `RefMut` for a component of the borrowed data.
1779+ /// On failure, the original guard is returned alongside with the error
1780+ /// returned by the closure.
1781+ ///
1782+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
1783+ ///
1784+ /// This is an associated function that needs to be used as
1785+ /// `RefMut::try_map(...)`. A method would interfere with methods of the same
1786+ /// name on the contents of a `RefCell` used through `Deref`.
1787+ ///
1788+ /// # Examples
1789+ ///
1790+ /// ```
1791+ /// #![feature(refcell_try_map)]
1792+ /// use std::cell::{RefCell, RefMut};
1793+ /// use std::str::{from_utf8_mut, Utf8Error};
1794+ ///
1795+ /// let c = RefCell::new(vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
1796+ /// {
1797+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1798+ /// let b2: Result<RefMut<'_, str>, _> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1799+ /// let mut b2 = b2.unwrap();
1800+ /// assert_eq!(&*b2, "hello");
1801+ /// b2.make_ascii_uppercase();
1802+ /// }
1803+ /// assert_eq!(*c.borrow(), "HELLO".as_bytes());
1804+ ///
1805+ /// let c = RefCell::new(vec![0xFF]);
1806+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1807+ /// let b2: Result<_, (RefMut<'_, Vec<u8>>, Utf8Error)> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1808+ /// let (b3, e) = b2.unwrap_err();
1809+ /// assert_eq!(*b3, vec![0xFF]);
1810+ /// assert_eq!(e.valid_up_to(), 0);
1811+ /// ```
1812+ #[ unstable( feature = "refcell_try_map" , issue = "143801" ) ]
1813+ #[ inline]
1814+ pub fn try_map < U : ?Sized , E > (
1815+ mut orig : RefMut < ' b , T > ,
1816+ f : impl FnOnce ( & mut T ) -> Result < & mut U , E > ,
1817+ ) -> Result < RefMut < ' b , U > , ( Self , E ) > {
1818+ // SAFETY: function holds onto an exclusive reference for the duration
1819+ // of its call through `orig`, and the pointer is only de-referenced
1820+ // inside of the function call never allowing the exclusive reference to
1821+ // escape.
1822+ match f ( & mut * orig) {
1823+ Ok ( value) => {
1824+ Ok ( RefMut { value : NonNull :: from ( value) , borrow : orig. borrow , marker : PhantomData } )
1825+ }
1826+ Err ( e) => Err ( ( orig, e) ) ,
1827+ }
1828+ }
1829+
17371830 /// Splits a `RefMut` into multiple `RefMut`s for different components of the
17381831 /// borrowed data.
17391832 ///
0 commit comments