forgotten 1.2.0

globally and safely persist a value, implemented with ManuallyDrop
Documentation
use std::{cell::RefCell, collections::HashMap, rc::Rc};

use num::{traits::ops::overflowing::OverflowingAdd, One, Zero};

#[derive(Debug)]
pub struct Forgotten<K, T: ?Sized> {
    cur: K,
    map: HashMap<K, Rc<T>>,
}

impl<K: Clone + Eq + std::hash::Hash + OverflowingAdd + Zero + One, T: ?Sized> Forgotten<K, T> {
    #[inline]
    fn find_available_key(&mut self) -> Option<K> {
        let mut k = self.cur.clone();

        loop {
            (k, _) = k.overflowing_add(&K::one());

            if k == self.cur {
                return None;
            }

            if !k.is_zero() && !self.map.contains_key(&k) {
                self.cur = k.clone();
                return Some(k);
            }
        }
    }

    #[inline]
    fn insert(&mut self, v: Rc<T>) -> K {
        let k = self.find_available_key().expect("Forgotten is full");

        #[cfg(not(debug_assertions))]
        self.map.insert(k, v);

        #[cfg(debug_assertions)]
        assert!(self.map.insert(k.clone(), v).is_none());

        k
    }

    pub fn new() -> Self {
        Self {
            cur: K::zero(),
            map: HashMap::new(),
        }
    }

    #[inline]
    pub fn forget(&mut self, v: T) -> K
    where
        T: Sized,
    {
        self.forget_rc(Rc::new(v))
    }

    #[inline]
    pub fn forget_and_get(&mut self, v: T) -> (K, Rc<T>)
    where
        T: Sized,
    {
        let v = Rc::new(v);
        let ret = Rc::clone(&v);
        (self.forget_rc(v), ret)
    }

    #[inline]
    pub fn forget_rc(&mut self, v: Rc<T>) -> K {
        let k = self.insert(v);
        k
    }

    #[inline]
    pub fn try_free(&mut self, k: &K) -> bool {
        let v = self.map.remove(k);

        v.is_some()
    }

    #[inline]
    pub fn try_get(&self, k: &K) -> Option<Rc<T>> {
        self.try_ref(k).map(Rc::clone)
    }

    #[inline]
    pub fn try_ref(&self, k: &K) -> Option<&Rc<T>> {
        self.map.get(k)
    }

    #[inline]
    pub fn try_take(&mut self, k: &K) -> Option<Rc<T>> {
        let v = self.map.remove(k);
        if let Some(v) = v {
            Some(v)
        } else {
            None
        }
    }
}

pub struct ForgottenRefCell<K, T: ?Sized>(std::cell::RefCell<Forgotten<K, T>>);

impl<K: Clone + Eq + std::hash::Hash + OverflowingAdd + Zero + One, T: ?Sized>
    ForgottenRefCell<K, T>
{
    pub fn new() -> Self {
        Self(RefCell::new(Forgotten::new()))
    }

    #[inline]
    pub fn forget(&self, v: T) -> K
    where
        T: Sized,
    {
        self.0.borrow_mut().forget(v)
    }

    #[inline]
    pub fn forget_and_get(&self, v: T) -> (K, Rc<T>)
    where
        T: Sized,
    {
        self.0.borrow_mut().forget_and_get(v)
    }

    #[inline]
    pub fn forget_rc(&self, v: Rc<T>) -> K {
        self.0.borrow_mut().forget_rc(v)
    }

    #[inline]
    pub fn try_free(&self, k: &K) -> bool {
        self.0.borrow_mut().try_free(k)
    }

    #[inline]
    pub fn try_get(&self, k: &K) -> Option<Rc<T>> {
        self.0.borrow().try_get(k)
    }

    #[inline]
    pub fn try_take(&self, k: &K) -> Option<Rc<T>> {
        self.0.borrow_mut().try_take(k)
    }
}