raii-map 0.1.0

Map and set types in Rust in which the presence of the entry in the data structure is tied to the lifetime of a RAII handle returned by the insertion
Documentation
//! [`Set`] and related items.

use alloc::collections::{btree_set::Iter, BTreeSet};
use owner_monad::{Owner, OwnerMut};

/// A set in which the presence of an entry is tied to the lifetime of a RAII
/// handle returned by the insertion.
#[derive(Debug, PartialEq, Eq)]
pub struct Set<T>(BTreeSet<T>);

impl<T: Ord> Set<T> {
    /// Creates a new, empty set.
    pub fn new() -> Self {
        Self::default()
    }

    /// Gets the number of items in the set.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Checks if the set is empty.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Gets an iterator over the contents of the set.
    pub fn iter(&self) -> Iter<T> {
        self.0.iter()
    }
}

impl<T: Ord> Default for Set<T> {
    fn default() -> Self {
        Self(Default::default())
    }
}

impl<T: Ord> IntoIterator for Set<T> {
    type Item = T;

    type IntoIter = <BTreeSet<T> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl<'a, T: Ord> IntoIterator for &'a Set<T> {
    type Item = &'a T;

    type IntoIter = <&'a BTreeSet<T> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        #[allow(clippy::into_iter_on_ref)]
        (&self.0).into_iter()
    }
}

/// A RAII handle to data in a [`Set`].
pub struct SetHandle<T: Ord, O: OwnerMut<Set<T>>> {
    item: T,
    owner: O,
}

impl<T: Ord, O: OwnerMut<Set<T>>> Drop for SetHandle<T, O> {
    fn drop(&mut self) {
        let item = &self.item;
        self.owner.with(|set| set.0.remove(item));
    }
}

impl<T: Ord, O: OwnerMut<Set<T>>> Owner<O> for SetHandle<T, O> {
    fn with<'a, U>(&'a self, f: impl FnOnce(&O) -> U) -> Option<U>
    where
        O: 'a,
    {
        Some(f(&self.owner))
    }
}

/// Inserts an item into a set, returning a handle to the data if successful. A
/// result of `None` indicates that either the set could not be accessed or the
/// item already exists.
pub fn insert<T: Clone + Ord, O: OwnerMut<Set<T>>>(
    mut owner: O,
    item: T,
) -> Option<SetHandle<T, O>> {
    if owner.with(|set| set.0.insert(item.clone()))? {
        Some(SetHandle { item, owner })
    } else {
        None
    }
}