use cmp::PartialEq;
use default::Default;
use marker::{Copy, Send, Sync, Sized};
-use ops::{Deref, DerefMut, Drop};
+use ops::{Deref, DerefMut, Drop, FnOnce};
use option::Option;
use option::Option::{None, Some};
_borrow: orig._borrow.clone(),
}
}
+
+ /// Make a new `Ref` for a component of the borrowed data.
+ ///
+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as `Ref::map(...)`.
+ /// A method would interfere with methods of the same name on the contents of a `RefCell`
+ /// used through `Deref`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # #![feature(cell_extras)]
+ /// use std::cell::{RefCell, Ref};
+ ///
+ /// let c = RefCell::new((5, 'b'));
+ /// let b1: Ref<(u32, char)> = c.borrow();
+ /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0);
+ /// assert_eq!(*b2, 5)
+ /// ```
+ #[unstable(feature = "cell_extras", reason = "recently added")]
+ #[inline]
+ pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
+ where F: FnOnce(&T) -> &U
+ {
+ Ref {
+ _value: f(orig._value),
+ _borrow: orig._borrow,
+ }
+ }
+
+ /// Make a new `Ref` for a optional component of the borrowed data, e.g. an enum variant.
+ ///
+ /// The `RefCell` is already immutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as `Ref::filter_map(...)`.
+ /// A method would interfere with methods of the same name on the contents of a `RefCell`
+ /// used through `Deref`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # #![feature(cell_extras)]
+ /// use std::cell::{RefCell, Ref};
+ ///
+ /// let c = RefCell::new(Ok(5));
+ /// let b1: Ref<Result<u32, ()>> = c.borrow();
+ /// let b2: Ref<u32> = Ref::filter_map(b1, |o| o.as_ref().ok()).unwrap();
+ /// assert_eq!(*b2, 5)
+ /// ```
+ #[unstable(feature = "cell_extras", reason = "recently added")]
+ #[inline]
+ pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>>
+ where F: FnOnce(&T) -> Option<&U>
+ {
+ f(orig._value).map(move |new| Ref {
+ _value: new,
+ _borrow: orig._borrow,
+ })
+ }
+}
+
+impl<'b, T: ?Sized> RefMut<'b, T> {
+ /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum variant.
+ ///
+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as `RefMut::map(...)`.
+ /// A method would interfere with methods of the same name on the contents of a `RefCell`
+ /// used through `Deref`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # #![feature(cell_extras)]
+ /// use std::cell::{RefCell, RefMut};
+ ///
+ /// let c = RefCell::new((5, 'b'));
+ /// {
+ /// let b1: RefMut<(u32, char)> = c.borrow_mut();
+ /// let mut b2: RefMut<u32> = RefMut::map(b1, |t| &mut t.0);
+ /// assert_eq!(*b2, 5);
+ /// *b2 = 42;
+ /// }
+ /// assert_eq!(*c.borrow(), (42, 'b'));
+ /// ```
+ #[unstable(feature = "cell_extras", reason = "recently added")]
+ #[inline]
+ pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
+ where F: FnOnce(&mut T) -> &mut U
+ {
+ RefMut {
+ _value: f(orig._value),
+ _borrow: orig._borrow,
+ }
+ }
+
+ /// Make a new `RefMut` for a optional component of the borrowed data, e.g. an enum variant.
+ ///
+ /// The `RefCell` is already mutably borrowed, so this cannot fail.
+ ///
+ /// This is an associated function that needs to be used as `RefMut::filter_map(...)`.
+ /// A method would interfere with methods of the same name on the contents of a `RefCell`
+ /// used through `Deref`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # #![feature(cell_extras)]
+ /// use std::cell::{RefCell, RefMut};
+ ///
+ /// let c = RefCell::new(Ok(5));
+ /// {
+ /// let b1: RefMut<Result<u32, ()>> = c.borrow_mut();
+ /// let mut b2: RefMut<u32> = RefMut::filter_map(b1, |o| o.as_mut().ok()).unwrap();
+ /// assert_eq!(*b2, 5);
+ /// *b2 = 42;
+ /// }
+ /// assert_eq!(*c.borrow(), Ok(42));
+ /// ```
+ #[unstable(feature = "cell_extras", reason = "recently added")]
+ #[inline]
+ pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>>
+ where F: FnOnce(&mut T) -> Option<&mut U>
+ {
+ let RefMut { _value, _borrow } = orig;
+ f(_value).map(move |new| RefMut {
+ _value: new,
+ _borrow: _borrow,
+ })
+ }
}
struct BorrowRefMut<'b> {
assert_eq!(x.borrow_state(), BorrowState::Unused);
}
+#[test]
+fn ref_map_does_not_update_flag() {
+ let x = RefCell::new(Some(5));
+ {
+ let b1: Ref<Option<u32>> = x.borrow();
+ assert_eq!(x.borrow_state(), BorrowState::Reading);
+ {
+ let b2: Ref<u32> = Ref::map(b1, |o| o.as_ref().unwrap());
+ assert_eq!(*b2, 5);
+ assert_eq!(x.borrow_state(), BorrowState::Reading);
+ }
+ assert_eq!(x.borrow_state(), BorrowState::Unused);
+ }
+ assert_eq!(x.borrow_state(), BorrowState::Unused);
+}
+
+#[test]
+fn ref_map_accessor() {
+ struct X(RefCell<(u32, char)>);
+ impl X {
+ fn accessor(&self) -> Ref<u32> {
+ Ref::map(self.0.borrow(), |tuple| &tuple.0)
+ }
+ }
+ let x = X(RefCell::new((7, 'z')));
+ let d: Ref<u32> = x.accessor();
+ assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_filter_map_accessor() {
+ struct X(RefCell<Result<u32, ()>>);
+ impl X {
+ fn accessor(&self) -> Option<Ref<u32>> {
+ Ref::filter_map(self.0.borrow(), |r| r.as_ref().ok())
+ }
+ }
+ let x = X(RefCell::new(Ok(7)));
+ let d: Ref<u32> = x.accessor().unwrap();
+ assert_eq!(*d, 7);
+}
+
+#[test]
+fn ref_mut_map_accessor() {
+ struct X(RefCell<(u32, char)>);
+ impl X {
+ fn accessor(&self) -> RefMut<u32> {
+ RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
+ }
+ }
+ let x = X(RefCell::new((7, 'z')));
+ {
+ let mut d: RefMut<u32> = x.accessor();
+ assert_eq!(*d, 7);
+ *d += 1;
+ }
+ assert_eq!(*x.0.borrow(), (8, 'z'));
+}
+
+#[test]
+fn ref_mut_filter_map_accessor() {
+ struct X(RefCell<Result<u32, ()>>);
+ impl X {
+ fn accessor(&self) -> Option<RefMut<u32>> {
+ RefMut::filter_map(self.0.borrow_mut(), |r| r.as_mut().ok())
+ }
+ }
+ let x = X(RefCell::new(Ok(7)));
+ {
+ let mut d: RefMut<u32> = x.accessor().unwrap();
+ assert_eq!(*d, 7);
+ *d += 1;
+ }
+ assert_eq!(*x.0.borrow(), Ok(8));
+}
+
#[test]
fn as_unsafe_cell() {
let c1: Cell<usize> = Cell::new(0);