bounded_graph 0.3.0

A thin newtype wrapper for `petgraph` to assist in the creation of graphs with restrictions on their edges
Documentation
#[cfg(feature = "serde-1")]
use serde::{Deserialize, Serialize};

/// A simple node type with fixed edge count limits.
///
/// This generic struct allows nodes to have a maximum number of incoming and outgoing edges.
/// The `data` field can store any user-defined data.
///
/// This is a convenience type for common use cases where nodes have fixed edge limits
/// and you don't need complex edge constraint logic.
///
/// # Type Parameters
///
/// * `MAX_IN` - The maximum number of incoming edges
/// * `MAX_OUT` - The maximum number of outgoing edges (defaults to `MAX_IN` for symmetric limits)
/// * `T` - The type of data stored in the node (defaults to `()`)
///
/// # Examples
///
/// Symmetric edge limits (same for incoming and outgoing):
/// ```
/// use bounded_graph::{BoundedGraph, FixedEdgeCount};
///
/// // Node with max 2 edges (both incoming and outgoing)
/// let mut graph = BoundedGraph::<FixedEdgeCount<2, 2>, ()>::new();
/// let n1 = graph.add_node(FixedEdgeCount::empty());
/// let n2 = graph.add_node(FixedEdgeCount::empty());
///
/// assert!(graph.add_edge(n1, n2, ()).is_ok());
/// ```
///
/// Asymmetric edge limits:
/// ```
/// use bounded_graph::{BoundedGraph, FixedEdgeCount};
///
/// // Node with max 2 incoming, 5 outgoing edges
/// let mut graph = BoundedGraph::<FixedEdgeCount<2, 5>, ()>::new();
/// let n1 = graph.add_node(FixedEdgeCount::empty());
/// let n2 = graph.add_node(FixedEdgeCount::empty());
/// let n3 = graph.add_node(FixedEdgeCount::empty());
///
/// // n1 can have up to 5 outgoing edges
/// assert!(graph.add_edge(n1, n2, ()).is_ok());
/// assert!(graph.add_edge(n1, n3, ()).is_ok());
/// ```
///
/// With custom data:
/// ```
/// use bounded_graph::{BoundedGraph, FixedEdgeCount};
///
/// #[derive(Debug)]
/// struct NodeData {
///     name: String,
///     value: i32,
/// }
///
/// let mut graph = BoundedGraph::<FixedEdgeCount<3, 3, NodeData>, ()>::new();
/// let n1 = graph.add_node(FixedEdgeCount::new(NodeData {
///     name: "node1".to_string(),
///     value: 42,
/// }));
///
/// assert_eq!(graph[n1].data.name, "node1");
/// assert_eq!(graph[n1].data.value, 42);
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(Serialize, Deserialize))]
pub struct FixedEdgeCount<const MAX_IN: usize, const MAX_OUT: usize = MAX_IN, T = ()> {
    /// User-defined data stored in the node
    pub data: T,
}

impl<const MAX_IN: usize, const MAX_OUT: usize, T> FixedEdgeCount<MAX_IN, MAX_OUT, T> {
    /// Creates a new node with the given data.
    ///
    /// # Examples
    ///
    /// ```
    /// use bounded_graph::FixedEdgeCount;
    ///
    /// let node = FixedEdgeCount::<3, 5, i32>::new(42);
    /// assert_eq!(node.data, 42);
    /// ```
    pub const fn new(data: T) -> Self {
        Self { data }
    }
}

impl<const MAX_IN: usize, const MAX_OUT: usize> FixedEdgeCount<MAX_IN, MAX_OUT, ()> {
    /// Creates a new node without data.
    ///
    /// This is a convenience method for nodes that don't need to store data.
    ///
    /// # Examples
    ///
    /// ```
    /// use bounded_graph::FixedEdgeCount;
    ///
    /// let node = FixedEdgeCount::<2, 3>::empty();
    /// assert_eq!(node.data, ());
    /// ```
    pub const fn empty() -> Self {
        Self { data: () }
    }
}

/// A simplified node type with symmetric edge count limits.
///
/// This is a convenience type alias for `FixedEdgeCount` where the maximum number
/// of incoming and outgoing edges is the same. Use this for most common cases
/// where nodes have equal limits in both directions.
///
/// # Type Parameters
///
/// * `MAX` - The maximum number of edges (both incoming and outgoing)
/// * `T` - The type of data stored in the node (defaults to `()`)
///
/// # Examples
///
/// Basic usage:
/// ```
/// use bounded_graph::{BoundedGraph, SymmetricFixedEdgeCount};
///
/// // Node with max 3 edges in each direction
/// let mut graph = BoundedGraph::<SymmetricFixedEdgeCount<3>, ()>::new();
/// let n1 = graph.add_node(SymmetricFixedEdgeCount::empty());
/// let n2 = graph.add_node(SymmetricFixedEdgeCount::empty());
///
/// assert!(graph.add_edge(n1, n2, ()).is_ok());
/// ```
///
/// With custom data:
/// ```
/// use bounded_graph::{BoundedGraph, SymmetricFixedEdgeCount};
///
/// let mut graph = BoundedGraph::<SymmetricFixedEdgeCount<3, String>, ()>::new();
/// let n1 = graph.add_node(SymmetricFixedEdgeCount::new("node1".to_string()));
///
/// assert_eq!(graph[n1].data, "node1");
/// ```
pub type SymmetricFixedEdgeCount<const MAX: usize, T = ()> = FixedEdgeCount<MAX, MAX, T>;