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