#[derive(Debug, Clone)]
pub struct Slot<T> {
name: String,
value: Option<T>,
}
impl<T> Slot<T> {
pub fn new(name: impl Into<String>) -> Self {
Self { name: name.into(), value: None }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn receive(&mut self, value: T) {
self.value = Some(value);
}
pub fn take(&mut self) -> Option<T> {
self.value.take()
}
pub fn peek(&self) -> Option<&T> {
self.value.as_ref()
}
pub fn is_ready(&self) -> bool {
self.value.is_some()
}
pub fn clear(&mut self) {
self.value = None;
}
}
impl<T: Default> Default for Slot<T> {
fn default() -> Self {
Self::new("")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_slot_is_not_ready() {
let s: Slot<i32> = Slot::new("x");
assert!(!s.is_ready());
assert_eq!(s.name(), "x");
}
#[test]
fn receive_makes_ready() {
let mut s = Slot::new("x");
s.receive(42i32);
assert!(s.is_ready());
}
#[test]
fn take_consumes_value() {
let mut s = Slot::new("x");
s.receive(7i32);
assert_eq!(s.take(), Some(7));
assert!(!s.is_ready());
}
#[test]
fn take_on_empty_returns_none() {
let mut s: Slot<i32> = Slot::new("x");
assert_eq!(s.take(), None);
}
#[test]
fn peek_does_not_consume() {
let mut s = Slot::new("x");
s.receive(5i32);
assert_eq!(s.peek(), Some(&5));
assert!(s.is_ready()); }
#[test]
fn receive_replaces_unconsumed_value() {
let mut s = Slot::new("x");
s.receive(1i32);
s.receive(2i32);
assert_eq!(s.take(), Some(2));
}
#[test]
fn clear_empties_slot() {
let mut s = Slot::new("x");
s.receive(99i32);
s.clear();
assert!(!s.is_ready());
}
}