From bffa402896670b5c78a9ec050d82a58ee98de6fb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 9 Sep 2017 12:05:00 +0300 Subject: [PATCH] feat: add LazyCell::try_borrow_with --- src/lib.rs | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bc2d4b2..ebcbae1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,12 +62,12 @@ impl LazyCell { /// Put a value into this cell. /// /// This function will return `Err(value)` is the cell is already full. - pub fn fill(&self, t: T) -> Result<(), T> { + pub fn fill(&self, value: T) -> Result<(), T> { let mut slot = unsafe { &mut *self.inner.get() }; if slot.is_some() { - return Err(t); + return Err(value); } - *slot = Some(t); + *slot = Some(value); Ok(()) } @@ -109,6 +109,18 @@ impl LazyCell { slot.as_ref().unwrap() } + /// Same as `borrow_with`, but allows the initializing function to fail. + pub fn try_borrow_with(&self, f: F) -> Result<&T, E> + where F: FnOnce() -> Result + { + let mut slot = unsafe { &mut *self.inner.get() }; + if !slot.is_some() { + *slot = Some(f()?); + } + + Ok(slot.as_ref().unwrap()) + } + /// Consumes this `LazyCell`, returning the underlying value. pub fn into_inner(self) -> Option { unsafe { self.inner.into_inner() } @@ -284,6 +296,28 @@ mod tests { assert_eq!(&1, value); } + #[test] + fn test_try_borrow_with_ok() { + let lazycell = LazyCell::new(); + let result = lazycell.try_borrow_with::<(), _>(|| Ok(1)); + assert_eq!(result, Ok(&1)); + } + + #[test] + fn test_try_borrow_with_err() { + let lazycell = LazyCell::<()>::new(); + let result = lazycell.try_borrow_with(|| Err(1)); + assert_eq!(result, Err(1)); + } + + #[test] + fn test_try_borrow_with_already_filled() { + let lazycell = LazyCell::new(); + lazycell.fill(1).unwrap(); + let result = lazycell.try_borrow_with::<(), _>(|| unreachable!()); + assert_eq!(result, Ok(&1)); + } + #[test] fn test_into_inner() { let lazycell = LazyCell::new();