Skip to content

Commit d50f6c0

Browse files
committed
Add GcCellRef::filter_map
Fixes #176. Signed-off-by: Anders Kaseorg <[email protected]>
1 parent d25e341 commit d50f6c0

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

Diff for: gc/src/lib.rs

+41
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,47 @@ impl<'a, T: ?Sized> GcCellRef<'a, T> {
781781
}
782782
}
783783

784+
/// Makes a new `GcCellRef` for an optional component of the borrowed data.
785+
/// The original guard is returned as an `Err(..)` if the closure returns
786+
/// `None`.
787+
///
788+
/// The `GcCell` is already immutably borrowed, so this cannot fail.
789+
///
790+
/// This is an associated function that needs to be used as
791+
/// `GcCellRef::filter_map(...)`. A method would interfere with methods of
792+
/// the same name on the contents of a `GcCellRef` used through `Deref`.
793+
///
794+
/// # Examples
795+
///
796+
/// ```
797+
/// use gc::{GcCell, GcCellRef};
798+
///
799+
/// let c = GcCell::new(vec![1, 2, 3]);
800+
/// let b1: GcCellRef<Vec<u32>> = c.borrow();
801+
/// let b2: Result<GcCellRef<u32>, _> = GcCellRef::filter_map(b1, |v| v.get(1));
802+
/// assert_eq!(*b2.unwrap(), 2);
803+
/// ```
804+
#[inline]
805+
pub fn filter_map<U, F>(orig: Self, f: F) -> Result<GcCellRef<'a, U>, Self>
806+
where
807+
U: ?Sized,
808+
F: FnOnce(&T) -> Option<&U>,
809+
{
810+
match f(orig.value) {
811+
None => Err(orig),
812+
Some(value) => {
813+
// We have to tell the compiler not to call the destructor of GcCellRef,
814+
// because it will update the borrow flags.
815+
let orig = ManuallyDrop::new(orig);
816+
817+
Ok(GcCellRef {
818+
flags: orig.flags,
819+
value,
820+
})
821+
}
822+
}
823+
}
824+
784825
/// Splits a `GcCellRef` into multiple `GcCellRef`s for different components of the borrowed data.
785826
///
786827
/// The `GcCell` is already immutably borrowed, so this cannot fail.

0 commit comments

Comments
 (0)