intrex 0.2.0

Intrusive collections with items addressed by indices
Documentation
//! Node access callback traits
use crate::node_data::{
    NodesData, NodesDataLend, NodesDataLendGat, NodesDataLendMut, NodesDataLendMutGat,
};

use super::*;

/// Read-only access for [`Link`]s stored in linked list elements.
///
/// This trait's methods take `&mut self` to provide maximize flexibility to
/// the implementors.
///
/// This is one of [the node access traits](crate::list#node-access-traits).
pub trait NodesLink<Index> {
    /// Get the [`Link`] of a specified element previously set via
    /// [`NodesLinkMut::replace_node_link`].
    fn node_link(&self, node: Index) -> Option<Link<Index>>;

    /// Get the [`Link`] of a specified element previously set via
    /// [`NodesLinkMut::replace_node_link`], expecting that it is set.
    #[inline]
    #[track_caller]
    fn expect_node_link(&self, node: Index) -> Link<Index> {
        self.node_link(node).expect("node not linked")
    }
}

/// Forwarding implementation
impl<T, Index> NodesLink<Index> for &T
where
    T: ?Sized + NodesLink<Index>,
{
    #[inline]
    #[track_caller]
    fn node_link(&self, node: Index) -> Option<Link<Index>> {
        (**self).node_link(node)
    }

    #[inline]
    #[track_caller]
    fn expect_node_link(&self, node: Index) -> Link<Index> {
        (**self).expect_node_link(node)
    }
}

/// Forwarding implementation
impl<T, Index> NodesLink<Index> for &mut T
where
    T: ?Sized + NodesLink<Index>,
{
    #[inline]
    #[track_caller]
    fn node_link(&self, node: Index) -> Option<Link<Index>> {
        (**self).node_link(node)
    }

    #[inline]
    #[track_caller]
    fn expect_node_link(&self, node: Index) -> Link<Index> {
        (**self).expect_node_link(node)
    }
}

/// Read-write access for [`Link`]s stored in linked list elements.
///
/// This is one of [the node access traits](crate::list#node-access-traits).
pub trait NodesLinkMut<Index> {
    /// Get the [`Link`] of a specified element previously set via
    /// [`NodesLinkMut::replace_node_link`].
    fn node_link(&mut self, node: Index) -> Option<Link<Index>>;

    /// Get the [`Link`] of a specified element previously set via
    /// [`NodesLinkMut::replace_node_link`], expecting that it is set.
    #[inline]
    #[track_caller]
    fn expect_node_link(&mut self, node: Index) -> Link<Index> {
        self.node_link(node).expect("node not linked")
    }

    /// Replace the [`Link`] of a specified element.
    fn replace_node_link(&mut self, node: Index, link: Option<Link<Index>>) -> Option<Link<Index>>;

    /// Update the [`Link`] of a specified element previously set via
    /// [`NodesLinkMut::replace_node_link`], using a provided closure.
    fn update_node_link(&mut self, node: Index, f: impl FnOnce(&mut Link<Index>));
}

/// Forwarding implementation
impl<T, Index> NodesLinkMut<Index> for &mut T
where
    T: ?Sized + NodesLinkMut<Index>,
{
    #[inline]
    #[track_caller]
    fn node_link(&mut self, node: Index) -> Option<Link<Index>> {
        (**self).node_link(node)
    }

    #[inline]
    #[track_caller]
    fn expect_node_link(&mut self, node: Index) -> Link<Index> {
        (**self).expect_node_link(node)
    }

    #[inline]
    #[track_caller]
    fn replace_node_link(&mut self, node: Index, link: Option<Link<Index>>) -> Option<Link<Index>> {
        (**self).replace_node_link(node, link)
    }

    #[inline]
    #[track_caller]
    fn update_node_link(&mut self, node: Index, f: impl FnOnce(&mut Link<Index>)) {
        (**self).update_node_link(node, f);
    }
}

/// A [`NodesLink`] implementation that looks up a linked list node by
/// `pool[index]` and uses a provided closure to borrow its [`Link`].
///
/// Used by [`Head::read_ref`].
#[derive(Debug)]
pub struct NodesWithMapLink<'pool, Pool: ?Sized, MapLink> {
    /// The underlying node pool.
    pub pool: &'pool Pool,
    /// The link transformation.
    pub map_link: MapLink,
}

/// A [`NodesLinkMut`] implementation that looks up a linked list node by
/// `pool[index]` and uses a provided closure to mutably borrow its [`Link`].
///
/// Used by [`Head::write_ref`].
#[derive(Debug)]
pub struct NodesWithMapLinkMut<'pool, Pool: ?Sized, MapLink> {
    /// The underlying node pool.
    pub pool: &'pool mut Pool,
    /// The link transformation.
    pub map_link: MapLink,
}

impl<'pool, Pool: ?Sized, MapLink> Clone for NodesWithMapLink<'pool, Pool, MapLink>
where
    MapLink: Clone,
{
    #[inline]
    fn clone(&self) -> Self {
        NodesWithMapLink {
            pool: self.pool,
            map_link: self.map_link.clone(),
        }
    }
}

impl<'pool, Pool: ?Sized, MapLink> Copy for NodesWithMapLink<'pool, Pool, MapLink> where
    MapLink: Copy
{
}

impl<'pool, Index, Pool, MapLink, Element> NodesLink<Index>
    for NodesWithMapLink<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    MapLink: Fn(&'pool Element) -> &'pool Option<Link<Index>>,
    Element: 'pool,
    Index: Clone + 'pool,
{
    #[inline]
    #[track_caller]
    fn node_link(&self, node: Index) -> Option<Link<Index>> {
        (self.map_link)(&self.pool[node]).clone()
    }
}

impl<'pool, Index, Pool, MapLink, Element> NodesData<Index>
    for NodesWithMapLink<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    type Data = &'pool Element;

    #[inline]
    #[track_caller]
    fn node_data(&self, node: Index) -> Self::Data {
        &self.pool[node]
    }
}

impl<'this, 'pool, Index, Pool, MapLink, Element> NodesDataLendGat<'this, Index>
    for NodesWithMapLink<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    type Data = &'pool Element;
}

impl<'pool, Index, Pool, MapLink, Element> NodesDataLend<Index>
    for NodesWithMapLink<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    #[inline]
    #[track_caller]
    fn node_data_lend(&self, node: Index) -> &'pool Element {
        &self.pool[node]
    }
}

impl<'pool, Index, Pool, MapLink, Element> NodesLinkMut<Index>
    for NodesWithMapLinkMut<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::IndexMut<Index, Output = Element>,
    MapLink: Fn(&mut Element) -> &mut Option<Link<Index>>,
    Element: 'pool,
    Index: Clone + 'pool,
{
    #[inline]
    #[track_caller]
    fn node_link(&mut self, node: Index) -> Option<Link<Index>> {
        (self.map_link)(&mut self.pool[node]).clone()
    }

    #[inline]
    #[track_caller]
    fn replace_node_link(&mut self, node: Index, link: Option<Link<Index>>) -> Option<Link<Index>> {
        core::mem::replace((self.map_link)(&mut self.pool[node]), link)
    }

    #[inline]
    #[track_caller]
    fn update_node_link(&mut self, node: Index, f: impl FnOnce(&mut Link<Index>)) {
        f((self.map_link)(&mut self.pool[node])
            .as_mut()
            .expect("node not linked"))
    }
}

impl<'this, 'pool, Index, Pool, MapLink, Element> NodesDataLendGat<'this, Index>
    for NodesWithMapLinkMut<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    type Data = &'this Element;
}

impl<'pool, Index, Pool, MapLink, Element> NodesDataLend<Index>
    for NodesWithMapLinkMut<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::Index<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    #[inline]
    #[track_caller]
    fn node_data_lend(&self, node: Index) -> &Element {
        &self.pool[node]
    }
}

impl<'this, 'pool, Index, Pool, MapLink, Element> NodesDataLendMutGat<'this, Index>
    for NodesWithMapLinkMut<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::IndexMut<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    type Data = &'this mut Element;
}

impl<'pool, Index, Pool, MapLink, Element> NodesDataLendMut<Index>
    for NodesWithMapLinkMut<'pool, Pool, MapLink>
where
    Pool: ?Sized + core::ops::IndexMut<Index, Output = Element>,
    Element: 'pool,
    Index: 'pool,
{
    #[inline]
    #[track_caller]
    fn node_data_lend_mut(&mut self, node: Index) -> &mut Element {
        &mut self.pool[node]
    }
}