ratio-interner 0.1.1

Ratio's value interner library.
Documentation
//! # Interner trait and implementations
//!
//! ## License
//!
//! This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
//! If a copy of the MPL was not distributed with this file,
//! You can obtain one at <https://mozilla.org/MPL/2.0/>.
//!
//! **Code examples both in the docstrings and rendered documentation are free to use.**

use std::borrow::Cow;

use snafu::prelude::*;

/// Interner error.
#[derive(Clone, Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum Error {
    /// Value already exists in store.
    ValueAlreadyExists,
    /// Key is no longer valid.
    InvalidKey,
    /// Value does not exist in this interner.
    ValueDoesNotExist,
}

/// Interner trait that interns values and returns keys for them.
/// - K: Key type.
/// - V: Value type.
pub trait Interner<K: Copy, V: Clone> {
    /// Intern (a reference to) a value. Returns the corresponding key.
    fn intern(&mut self, value: Cow<'_, V>) -> K;

    /// Try to intern a new value and raise an error if it already exists.
    fn try_intern(&mut self, value: Cow<'_, V>) -> Result<K, Error>;

    /// Intern an owned value.
    fn intern_owned(&mut self, value: V) -> K {
        self.intern(Cow::Owned(value))
    }

    /// Intern a borrowed value.
    fn intern_borrowed(&mut self, value: &V) -> K {
        self.intern(Cow::Borrowed(value))
    }

    /// Remove a key and return the removed value if it existed.
    fn remove_key(&mut self, key: K) -> Option<V>;

    /// Try to remove an entry by key.
    fn try_remove_key(&mut self, key: K) -> Result<V, Error> {
        match self.remove_key(key) {
            Some(value) => Ok(value),
            None => InvalidKeySnafu.fail(),
        }
    }

    /// Try to update the value for an existing key and raise a value if the value already exists
    /// for another key.
    fn try_update(&mut self, key: K, value: Cow<'_, V>) -> Result<V, Error>;

    /// Remove a value and returns the corresponding key if it existed.
    fn remove_value(&mut self, value: &V) -> Option<K>;

    /// Try to remove an entry by value and return the corresponding key if it existed.
    fn try_remove_value(&mut self, value: &V) -> Result<K, Error> {
        self.remove_value(value).context(ValueDoesNotExistSnafu)
    }

    /// Clear all entries in this map.
    fn clear(&mut self);

    /// The number of items interned.
    fn len(&self) -> usize;

    /// Whether the interner is empty.
    fn is_empty(&self) -> bool;

    /// Check whether the interner has some key.
    fn contains_key(&self, key: K) -> bool;

    /// Check whether the interner has some value.
    fn contains_value(&self, value: &V) -> bool;

    /// Get the key corresponding to a value.
    fn get_key(&self, value: &V) -> Option<K>;

    /// Try to get the key corresponding to a value and raise an error if the value isn't interned.
    fn try_get_key(&self, value: &V) -> Result<K, Error> {
        self.get_key(value).context(ValueDoesNotExistSnafu)
    }

    /// Get an interned value using its key.
    fn get_value(&self, key: K) -> Option<&V>;

    /// Try to get an interned value or throw an error.
    fn try_get_value(&self, key: K) -> Result<&V, Error> {
        self.get_value(key).context(InvalidKeySnafu)
    }

    /// Iterator over all keys.
    fn keys(&self) -> impl Iterator<Item = K>;

    /// Iterator over all values.
    fn values<'a>(&'a self) -> impl Iterator<Item = &'a V>
    where
        V: 'a;

    /// Iterator over all key-value pairs in this interner.
    fn items<'a>(&'a self) -> impl Iterator<Item = (K, &'a V)>
    where
        V: 'a;
}