@@ -1559,6 +1559,47 @@ impl<'b, T: ?Sized> Ref<'b, T> {
15591559 }
15601560 }
15611561
1562+ /// Tries to makes a new `Ref` for a component of the borrowed data.
1563+ /// On failure, the original guard is returned alongside with the error
1564+ /// returned by the closure.
1565+ ///
1566+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
1567+ ///
1568+ /// This is an associated function that needs to be used as
1569+ /// `Ref::try_map(...)`. A method would interfere with methods of the same
1570+ /// name on the contents of a `RefCell` used through `Deref`.
1571+ ///
1572+ /// # Examples
1573+ ///
1574+ /// ```
1575+ /// #![feature(refcell_try_map)]
1576+ /// use std::cell::{RefCell, Ref};
1577+ /// use std::str::{from_utf8, Utf8Error};
1578+ ///
1579+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6 ,0x80]);
1580+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1581+ /// let b2: Result<Ref<'_, str>, _> = Ref::try_map(b1, |v| from_utf8(v));
1582+ /// assert_eq!(&*b2.unwrap(), "🦀");
1583+ ///
1584+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6]);
1585+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1586+ /// let b2: Result<_, (Ref<'_, Vec<u8>>, Utf8Error)> = Ref::try_map(b1, |v| from_utf8(v));
1587+ /// let (b3, e) = b2.unwrap_err();
1588+ /// assert_eq!(*b3, vec![0xF0, 0x9F, 0xA6]);
1589+ /// assert_eq!(e.valid_up_to(), 0);
1590+ /// ```
1591+ #[ unstable( feature = "refcell_try_map" , issue = "none" ) ]
1592+ #[ inline]
1593+ pub fn try_map < U : ?Sized , E , F > ( orig : Ref < ' b , T > , f : F ) -> Result < Ref < ' b , U > , ( Self , E ) >
1594+ where
1595+ F : FnOnce ( & T ) -> Result < & U , E > ,
1596+ {
1597+ match f ( & * orig) {
1598+ Ok ( value) => Ok ( Ref { value : NonNull :: from ( value) , borrow : orig. borrow } ) ,
1599+ Err ( e) => Err ( ( orig, e) ) ,
1600+ }
1601+ }
1602+
15621603 /// Splits a `Ref` into multiple `Ref`s for different components of the
15631604 /// borrowed data.
15641605 ///
@@ -1719,6 +1760,61 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
17191760 }
17201761 }
17211762
1763+ /// Tries to makes a new `RefMut` for a component of the borrowed data.
1764+ /// On failure, the original guard is returned alongside with the error
1765+ /// returned by the closure.
1766+ ///
1767+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
1768+ ///
1769+ /// This is an associated function that needs to be used as
1770+ /// `RefMut::try_map(...)`. A method would interfere with methods of the same
1771+ /// name on the contents of a `RefCell` used through `Deref`.
1772+ ///
1773+ /// # Examples
1774+ ///
1775+ /// ```
1776+ /// #![feature(refcell_try_map)]
1777+ /// use std::cell::{RefCell, RefMut};
1778+ /// use std::str::{from_utf8_mut, Utf8Error};
1779+ ///
1780+ /// let c = RefCell::new(vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
1781+ /// {
1782+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1783+ /// let b2: Result<RefMut<'_, str>, _> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1784+ /// let mut b2 = b2.unwrap();
1785+ /// assert_eq!(&*b2, "hello");
1786+ /// b2.make_ascii_uppercase();
1787+ /// }
1788+ /// assert_eq!(*c.borrow(), "HELLO".as_bytes());
1789+ ///
1790+ /// let c = RefCell::new(vec![0xFF]);
1791+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1792+ /// let b2: Result<_, (RefMut<'_, Vec<u8>>, Utf8Error)> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1793+ /// let (b3, e) = b2.unwrap_err();
1794+ /// assert_eq!(*b3, vec![0xFF]);
1795+ /// assert_eq!(e.valid_up_to(), 0);
1796+ /// ```
1797+ #[ unstable( feature = "refcell_try_map" , issue = "none" ) ]
1798+ #[ inline]
1799+ pub fn try_map < U : ?Sized , E , F > (
1800+ mut orig : RefMut < ' b , T > ,
1801+ f : F ,
1802+ ) -> Result < RefMut < ' b , U > , ( Self , E ) >
1803+ where
1804+ F : FnOnce ( & mut T ) -> Result < & mut U , E > ,
1805+ {
1806+ // SAFETY: function holds onto an exclusive reference for the duration
1807+ // of its call through `orig`, and the pointer is only de-referenced
1808+ // inside of the function call never allowing the exclusive reference to
1809+ // escape.
1810+ match f ( & mut * orig) {
1811+ Ok ( value) => {
1812+ Ok ( RefMut { value : NonNull :: from ( value) , borrow : orig. borrow , marker : PhantomData } )
1813+ }
1814+ Err ( e) => Err ( ( orig, e) ) ,
1815+ }
1816+ }
1817+
17221818 /// Splits a `RefMut` into multiple `RefMut`s for different components of the
17231819 /// borrowed data.
17241820 ///
0 commit comments