naia-shared 0.15.0

Common functionality shared between naia-server & naia-client crates
Documentation
use std::{
    collections::{
        hash_map::{Iter, IterMut},
        HashMap,
    },
    hash::Hash,
    iter::Map,
    marker::PhantomData,
};

pub trait BigMapKey: Clone + Copy + Eq + PartialEq + Hash {
    fn to_u64(&self) -> u64;
    fn from_u64(value: u64) -> Self;
}

pub struct BigMap<K: BigMapKey, V> {
    inner: HashMap<u64, V>,
    current_index: u64,
    phantom_k: PhantomData<K>,
}

impl<K: BigMapKey, V> Default for BigMap<K, V> {
    fn default() -> Self {
        Self {
            inner: HashMap::default(),
            current_index: 0,
            phantom_k: PhantomData,
        }
    }
}

impl<K: BigMapKey, V> BigMap<K, V> {
    pub fn get(&self, key: &K) -> Option<&V> {
        self.inner.get(&key.to_u64())
    }

    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
        self.inner.get_mut(&key.to_u64())
    }

    pub fn insert(&mut self, value: V) -> K {
        let old_index = self.current_index;
        self.current_index = self.current_index.wrapping_add(1);

        self.inner.insert(old_index, value);

        K::from_u64(old_index)
    }

    pub fn remove(&mut self, key: &K) -> Option<V> {
        self.inner.remove(&key.to_u64())
    }

    pub fn contains_key(&self, key: &K) -> bool {
        self.inner.contains_key(&key.to_u64())
    }

    #[allow(clippy::type_complexity)]
    pub fn iter<'a>(&'a self) -> Map<Iter<'_, u64, V>, fn((&'a u64, &'a V)) -> (K, &'a V)> {
        return self
            .inner
            .iter()
            .map(|(key, value)| (K::from_u64(*key), value));
    }

    #[allow(clippy::type_complexity)]
    pub fn iter_mut<'a>(
        &'a mut self,
    ) -> Map<IterMut<'_, u64, V>, fn((&'a u64, &'a mut V)) -> (K, &'a mut V)> {
        return self
            .inner
            .iter_mut()
            .map(|(key, value)| (K::from_u64(*key), value));
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}