Rollup merge of #118087 - GrigorenkoPV:refcell_try_map, r=Mark-Simula… · jieyouxu/rust@324bf2b (original) (raw)
`@@ -1573,6 +1573,47 @@ impl<'b, T: ?Sized> Ref<'b, T> {
`
1573
1573
`}
`
1574
1574
`}
`
1575
1575
``
``
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> = 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> = c.borrow();
`
``
1600
`+
/// let b2: Result<_, (Ref<'_, Vec>, 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
+
1576
1617
`` /// Splits a Ref into multiple Refs for different components of the
``
1577
1618
`/// borrowed data.
`
1578
1619
`///
`
`@@ -1734,6 +1775,58 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
`
1734
1775
`}
`
1735
1776
`}
`
1736
1777
``
``
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> = 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> = c.borrow_mut();
`
``
1807
`+
/// let b2: Result<_, (RefMut<'_, Vec>, 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
+
1737
1830
`` /// Splits a RefMut into multiple RefMuts for different components of the
``
1738
1831
`/// borrowed data.
`
1739
1832
`///
`