arrayset 3.1.1

An array-backed ordered set type.
Documentation
use super::OrdMap;

#[derive(Debug)]
pub struct VacantEntry<'a, K, V, const N: usize> {
    map: &'a mut OrdMap<K, V, N>,
    key: K,
    /// The index that the entry would be inserted into.
    index: usize,
}

impl<'a, K, V, const N: usize> VacantEntry<'a, K, V, N> {
    pub fn into_key(self) -> K {
        self.key
    }
    pub fn key(&self) -> &K {
        &self.key
    }
    /// The index this entry would insert at
    pub fn index(&self) -> usize {
        self.index
    }
    /// Try to insert a value into the map.  Returns the key and value on error.
    pub fn insert(self, value: V) -> Result<&'a mut V, (K, V)> {
        self.map
            .insert_at(self.index, self.key, value)
            .map(|()| &mut self.map.values_mut_slice()[self.index])
    }
}

#[derive(Debug)]
pub struct OccupiedEntry<'a, K, V, const N: usize> {
    pub(super) map: &'a mut OrdMap<K, V, N>,
    /// The index that the key occupies.
    pub(super) index: usize,
}

impl<'a, K, V, const N: usize> OccupiedEntry<'a, K, V, N> {
    /// A reference to the key in the map.
    pub fn key(&self) -> &K {
        &self.map.keys_slice()[self.index]
    }

    /// A reference to the value in the map.
    pub fn get(&self) -> &V {
        &self.map.values_slice()[self.index]
    }

    /// A reference to the value in the map.
    pub fn get_mut(&mut self) -> &mut V {
        &mut self.map.values_mut_slice()[self.index]
    }

    /// A reference to the value in the map.
    pub fn into_mut(self) -> &'a mut V {
        &mut self.map.values_mut_slice()[self.index]
    }

    /// The index this entry would insert at
    pub fn index(&self) -> usize {
        self.index
    }

    /// Replace the old value in the map.
    pub fn replace(&mut self, value: V) -> V {
        core::mem::replace(&mut self.map.values_mut_slice()[self.index], value)
    }

    /// Remove the old value from the map.
    pub fn remove(self) -> V {
        self.map.remove_at(self.index).1
    }
    /// Remove the old value from the map, returning both the key and value
    pub fn remove_key_value(self) -> (K, V) {
        self.map.remove_at(self.index)
    }
}

#[derive(Debug)]
pub enum Entry<'a, K, V, const N: usize>
// where
//     K: 'a,
//     V: 'a,
{
    Vacant(VacantEntry<'a, K, V, N>),
    Occupied(OccupiedEntry<'a, K, V, N>),
}

impl<'a, K, V, const N: usize> Entry<'a, K, V, N> {
    pub(super) fn occupied(map: &'a mut OrdMap<K, V, N>, index: usize) -> Self {
        Entry::Occupied(OccupiedEntry { map, index })
    }
    pub(super) fn vacant(map: &'a mut OrdMap<K, V, N>, index: usize, key: K) -> Self {
        Entry::Vacant(VacantEntry { map, key, index })
    }

    pub fn and_modify<F>(self, f: F) -> Self
    where
        F: FnOnce(&mut V),
    {
        match self {
            Entry::Vacant(entry) => Entry::Vacant(entry),
            Entry::Occupied(mut entry) => {
                f(entry.get_mut());
                Entry::Occupied(entry)
            }
        }
    }

    pub fn key(&self) -> &K {
        match self {
            Entry::Vacant(entry) => &entry.key,
            Entry::Occupied(entry) => &entry.key(),
        }
    }

    /// Insert the default value if vacant.  If the map is full, return the key as an Err.
    /// If the map was full, a default is not constructed.
    pub fn or_default(self) -> Result<&'a mut V, K>
    where
        V: Default,
    {
        self.or_insert_with(Default::default)
    }

    /// Insert the value if vacant.  If the map is full, return the key and value as an Err.
    pub fn or_insert(self, value: V) -> Result<&'a mut V, (K, V)> {
        match self {
            Entry::Vacant(entry) => entry.insert(value),
            Entry::Occupied(entry) => Ok(entry.into_mut()),
        }
    }

    /// Insert the value if vacant.  If the map is full, return the key, and the function is not executed.
    pub fn or_insert_with<F>(self, function: F) -> Result<&'a mut V, K>
    where
        F: FnOnce() -> V,
    {
        match self {
            Entry::Vacant(entry) => {
                if entry.map.len < N {
                    match entry.insert(function()) {
                        Ok(v) => Ok(v),
                        Err(_) => unreachable!(),
                    }
                } else {
                    Err(entry.key)
                }
            }
            Entry::Occupied(entry) => Ok(entry.into_mut()),
        }
    }

    /// Insert the value if vacant.  If the map is full, return the key, and the function is not executed.
    pub fn or_insert_with_key<F>(self, function: F) -> Result<&'a mut V, K>
    where
        F: FnOnce(&K) -> V,
    {
        match self {
            Entry::Vacant(entry) => {
                if entry.map.len < N {
                    let value = function(&entry.key);
                    match entry.insert(value) {
                        Ok(v) => Ok(v),
                        Err(_) => unreachable!(),
                    }
                } else {
                    Err(entry.key)
                }
            }
            Entry::Occupied(entry) => Ok(entry.into_mut()),
        }
    }
}