#![deny(missing_docs)]
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
use std::cell::RefCell;
use std::mem;
pub struct LazyCell<T> {
inner: RefCell<Option<T>>,
}
impl<T> LazyCell<T> {
pub fn new() -> LazyCell<T> {
LazyCell { inner: RefCell::new(None) }
}
pub fn fill(&self, t: T) {
let mut slot = self.inner.borrow_mut();
if slot.is_some() {
panic!("lazy cell is already filled")
}
*slot = Some(t);
}
pub fn filled(&self) -> bool {
self.inner.borrow().is_some()
}
pub fn borrow(&self) -> Option<&T> {
match *self.inner.borrow() {
Some(ref inner) => unsafe { Some(mem::transmute(inner)) },
None => None,
}
}
pub fn into_inner(self) -> Option<T> {
self.inner.into_inner()
}
}
#[cfg(test)]
mod tests {
use super::LazyCell;
#[test]
fn test_borrow_from_empty() {
let lazycell: LazyCell<usize> = LazyCell::new();
let value = lazycell.borrow();
assert_eq!(value, None);
}
#[test]
fn test_fill_and_borrow() {
let lazycell = LazyCell::new();
assert!(!lazycell.filled());
lazycell.fill(1);
assert!(lazycell.filled());
let value = lazycell.borrow();
assert_eq!(value, Some(&1));
}
#[test]
#[should_panic(expected = "lazy cell is already filled")]
fn test_already_filled_panic() {
let lazycell = LazyCell::new();
lazycell.fill(1);
lazycell.fill(1);
}
#[test]
fn test_into_inner() {
let lazycell = LazyCell::new();
lazycell.fill(1);
let value = lazycell.into_inner();
assert_eq!(value, Some(1));
}
}