mapgraph 0.12.0

A directed graph that can also be used as an arbitrary map.
Documentation
//! Contains types used to implement entry API on [`Graph`](crate::Graph)s.

use crate::{
    error::RemoveNodeError,
    graph::Node,
    map::{MapWithEntry, OccupiedMapEntry, VacantMapEntry},
};
use core::{
    fmt::{self, Debug},
    mem,
};

/// An occupied node entry.
#[derive(Debug)]
pub struct OccupiedEntry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI> + 'a,
{
    pub(super) entry: NM::OccupiedEntry<'a>,
}

impl<'a, N, NI, EI, NM> OccupiedEntry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI> + 'a,
{
    /// Returns an immutable reference to the value of an entry.
    pub fn get(&self) -> &N {
        &self.entry.get().weight
    }

    /// Returns a mutable reference to the value of an entry.
    pub fn get_mut(&mut self) -> &mut N {
        &mut self.entry.get_mut().weight
    }

    /// Converts the [`OccupiedEntry`]` into a mutable reference to the value in the entry with a
    /// lifetime bound to the map itself.
    pub fn into_mut(self) -> &'a mut N {
        &mut self.entry.into_mut().weight
    }

    /// Replaces the weight of the node the entry refers to.
    pub fn replace(&mut self, value: N) -> N {
        mem::replace(&mut self.entry.get_mut().weight, value)
    }

    /// Removes a node the entry points to from the graph.
    ///
    /// # Errors
    ///
    /// Returns a [`RemoveNodeError`] in case the node is still connected when being removed.
    pub fn remove(self) -> Result<N, RemoveNodeError> {
        let node = self.entry.get();
        if node.next_outgoing_edge.is_none() && node.next_incoming_edge.is_none() {
            Ok(self.entry.remove().weight)
        } else {
            Err(RemoveNodeError)
        }
    }
}

/// A vacant node entry.
#[derive(Debug)]
pub struct VacantEntry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI> + 'a,
{
    pub(super) entry: NM::VacantEntry<'a>,
}

impl<'a, N, NI, EI, NM> VacantEntry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI> + 'a,
{
    /// Inserts a value for the entry's key.
    pub fn insert<'l>(self, weight: N) -> &'l mut N
    where
        Self: 'l,
    {
        &mut self
            .entry
            .insert(Node {
                weight,
                next_incoming_edge: None,
                next_outgoing_edge: None,
            })
            .weight
    }
}

/// A graph node entry.
pub enum Entry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI>,
{
    /// An occupied graph node.
    Occupied(OccupiedEntry<'a, N, NI, EI, NM>),
    /// A vacant graph node.
    Vacant(VacantEntry<'a, N, NI, EI, NM>),
}

impl<'a, N, NI, EI, NM> Entry<'a, N, NI, EI, NM>
where
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI>,
{
    /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable
    /// reference to the value in the entry.
    pub fn or_insert(self, default: N) -> &'a mut N {
        match self {
            Entry::Vacant(entry) => entry.insert(default),
            Entry::Occupied(entry) => entry.into_mut(),
        }
    }

    /// Ensures a value is in the entry by inserting the result of the default function if empty,
    /// and returns a mutable reference to the value in the entry.
    pub fn or_insert_with<F: FnOnce() -> N>(self, f: F) -> &'a mut N {
        match self {
            Entry::Vacant(entry) => entry.insert(f()),
            Entry::Occupied(entry) => entry.into_mut(),
        }
    }
}

impl<'a, N, NI, EI, NM> Debug for Entry<'a, N, NI, EI, NM>
where
    N: Debug,
    NI: Copy + Eq + Debug + 'static,
    EI: Copy + Eq + Debug + 'static,
    NM: MapWithEntry<Node<N, EI>, Key = NI> + Debug,
    NM::VacantEntry<'a>: Debug,
    NM::OccupiedEntry<'a>: Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Entry::Vacant(entry) => f.debug_tuple("Entry::Vacant").field(entry).finish(),
            Entry::Occupied(entry) => f.debug_tuple("Entry::Occupied").field(entry).finish(),
        }
    }
}