sigwake 0.0.1

A thread-safe signal-based state management library that integrates with Rust's async programming model
Documentation
use std::collections::{BTreeMap, btree_map};

#[cfg(test)]
mod tests;

pub struct BTreeMultiMap<K, V> {
    entries: BTreeMap<(K, usize), V>,
    ids: BTreeMap<K, usize>,
}

impl<K, V> BTreeMultiMap<K, V>
where
    K: Ord + Copy,
{
    pub const fn new() -> Self {
        Self {
            entries: BTreeMap::new(),
            ids: BTreeMap::new(),
        }
    }
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    pub fn insert(&mut self, key: K, value: V) -> usize {
        let mut e_id = self.ids.entry(key);
        let mut need_save_id = false;
        let mut id = match &mut e_id {
            btree_map::Entry::Vacant(_) => 0,
            btree_map::Entry::Occupied(e) => {
                need_save_id = true;
                e.get().wrapping_add(1)
            }
        };

        loop {
            match self.entries.entry((key, id)) {
                btree_map::Entry::Vacant(e) => {
                    e.insert(value);
                    if need_save_id {
                        e_id.and_modify(|x| *x = id).or_insert(id);
                    }
                    return id;
                }
                btree_map::Entry::Occupied(_) => {
                    id = id.wrapping_add(1);
                    need_save_id = true;
                }
            }
        }
    }
    pub fn remove(&mut self, key: K, id: usize) -> Option<V> {
        let ret = self.entries.remove(&(key, id));
        if self.first_key() != Some(&key) {
            self.ids.remove(&key);
        }
        ret
    }
    pub fn first_key(&self) -> Option<&K> {
        Some(&self.entries.first_key_value()?.0.0)
    }
    pub fn first_entry(&mut self) -> Option<btree_map::OccupiedEntry<(K, usize), V>> {
        self.entries.first_entry()
    }
}