@@ -1547,6 +1547,47 @@ impl<'b, T: ?Sized> Ref<'b, T> {
15471547 }
15481548 }
15491549
1550+ /// Tries to makes a new `Ref` for a component of the borrowed data.
1551+ /// On failure, the original guard is returned alongside with the error
1552+ /// returned by the closure.
1553+ ///
1554+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
1555+ ///
1556+ /// This is an associated function that needs to be used as
1557+ /// `Ref::try_map(...)`. A method would interfere with methods of the same
1558+ /// name on the contents of a `RefCell` used through `Deref`.
1559+ ///
1560+ /// # Examples
1561+ ///
1562+ /// ```
1563+ /// #![feature(refcell_try_map)]
1564+ /// use std::cell::{RefCell, Ref};
1565+ /// use std::str::{from_utf8, Utf8Error};
1566+ ///
1567+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6 ,0x80]);
1568+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1569+ /// let b2: Result<Ref<'_, str>, _> = Ref::try_map(b1, |v| from_utf8(v));
1570+ /// assert_eq!(&*b2.unwrap(), "🦀");
1571+ ///
1572+ /// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6]);
1573+ /// let b1: Ref<'_, Vec<u8>> = c.borrow();
1574+ /// let b2: Result<_, (Ref<'_, Vec<u8>>, Utf8Error)> = Ref::try_map(b1, |v| from_utf8(v));
1575+ /// let (b3, e) = b2.unwrap_err();
1576+ /// assert_eq!(*b3, vec![0xF0, 0x9F, 0xA6]);
1577+ /// assert_eq!(e.valid_up_to(), 0);
1578+ /// ```
1579+ #[ unstable( feature = "refcell_try_map" , issue = "none" ) ]
1580+ #[ inline]
1581+ pub fn try_map < U : ?Sized , E , F > ( orig : Ref < ' b , T > , f : F ) -> Result < Ref < ' b , U > , ( Self , E ) >
1582+ where
1583+ F : FnOnce ( & T ) -> Result < & U , E > ,
1584+ {
1585+ match f ( & * orig) {
1586+ Ok ( value) => Ok ( Ref { value : NonNull :: from ( value) , borrow : orig. borrow } ) ,
1587+ Err ( e) => Err ( ( orig, e) ) ,
1588+ }
1589+ }
1590+
15501591 /// Splits a `Ref` into multiple `Ref`s for different components of the
15511592 /// borrowed data.
15521593 ///
@@ -1707,6 +1748,61 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
17071748 }
17081749 }
17091750
1751+ /// Tries to makes a new `RefMut` for a component of the borrowed data.
1752+ /// On failure, the original guard is returned alongside with the error
1753+ /// returned by the closure.
1754+ ///
1755+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
1756+ ///
1757+ /// This is an associated function that needs to be used as
1758+ /// `RefMut::try_map(...)`. A method would interfere with methods of the same
1759+ /// name on the contents of a `RefCell` used through `Deref`.
1760+ ///
1761+ /// # Examples
1762+ ///
1763+ /// ```
1764+ /// #![feature(refcell_try_map)]
1765+ /// use std::cell::{RefCell, RefMut};
1766+ /// use std::str::{from_utf8_mut, Utf8Error};
1767+ ///
1768+ /// let c = RefCell::new(vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);
1769+ /// {
1770+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1771+ /// let b2: Result<RefMut<'_, str>, _> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1772+ /// let mut b2 = b2.unwrap();
1773+ /// assert_eq!(&*b2, "hello");
1774+ /// b2.make_ascii_uppercase();
1775+ /// }
1776+ /// assert_eq!(*c.borrow(), "HELLO".as_bytes());
1777+ ///
1778+ /// let c = RefCell::new(vec![0xFF]);
1779+ /// let b1: RefMut<'_, Vec<u8>> = c.borrow_mut();
1780+ /// let b2: Result<_, (RefMut<'_, Vec<u8>>, Utf8Error)> = RefMut::try_map(b1, |v| from_utf8_mut(v));
1781+ /// let (b3, e) = b2.unwrap_err();
1782+ /// assert_eq!(*b3, vec![0xFF]);
1783+ /// assert_eq!(e.valid_up_to(), 0);
1784+ /// ```
1785+ #[ unstable( feature = "refcell_try_map" , issue = "none" ) ]
1786+ #[ inline]
1787+ pub fn try_map < U : ?Sized , E , F > (
1788+ mut orig : RefMut < ' b , T > ,
1789+ f : F ,
1790+ ) -> Result < RefMut < ' b , U > , ( Self , E ) >
1791+ where
1792+ F : FnOnce ( & mut T ) -> Result < & mut U , E > ,
1793+ {
1794+ // SAFETY: function holds onto an exclusive reference for the duration
1795+ // of its call through `orig`, and the pointer is only de-referenced
1796+ // inside of the function call never allowing the exclusive reference to
1797+ // escape.
1798+ match f ( & mut * orig) {
1799+ Ok ( value) => {
1800+ Ok ( RefMut { value : NonNull :: from ( value) , borrow : orig. borrow , marker : PhantomData } )
1801+ }
1802+ Err ( e) => Err ( ( orig, e) ) ,
1803+ }
1804+ }
1805+
17101806 /// Splits a `RefMut` into multiple `RefMut`s for different components of the
17111807 /// borrowed data.
17121808 ///
0 commit comments