1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
use std::ops::{Deref, DerefMut};
/// A data container that can offer ownership of its stored information
pub struct OfferCell<T> {
item: Option<T>,
}
impl<T> Default for OfferCell<T> {
fn default() -> Self {
Self::empty()
}
}
impl<T> OfferCell<T> {
/// Returns an empty cell
pub fn empty() -> Self {
Self { item: None }
}
/// Returns a new cell that stores `item`
pub fn new(item: T) -> Self {
Self { item: Some(item) }
}
/// Returns a reference to the stored item
pub fn item(&self) -> Option<&T> {
self.item.as_ref()
}
/// Returns a mutable reference to the stored item
pub fn item_mut(&mut self) -> Option<&mut T> {
self.item.as_mut()
}
/// Offers optional ownership of the stored data as a [`Offered`] item
pub fn offer(&mut self) -> Option<Offered<T>> {
// offering expects to always hold data
// so we must check if there is no data stored first
if self.item.is_none() {
return None;
}
Some(Offered {
item: &mut self.item,
})
}
}
/// A ownership offering that comes from a [`OfferCell`]
pub struct Offered<'a, T> {
item: &'a mut Option<T>,
}
impl<'a, T> Deref for Offered<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match &self.item {
Some(item) => item,
_ => unreachable!(),
}
}
}
impl<'a, T> DerefMut for Offered<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match &mut self.item {
Some(item) => item,
_ => unreachable!(),
}
}
}
impl<'a, T> Offered<'a, T> {
/// Consumes the offering, and takes ownership of the data
pub fn take(self) -> T {
match self.item.take() {
Some(item) => item,
None => unreachable!(),
}
}
}