alvidir/graph/
mod.rs

1//! Graph related definitions.
2
3use std::collections::BTreeMap;
4
5use crate::id::Identify;
6
7mod proxy;
8pub use proxy::*;
9
10/// An arbitrary graph.
11#[derive(Debug)]
12pub struct Graph<T: Identify> {
13    /// All the nodes in the graph.
14    nodes: BTreeMap<T::Id, T>,
15}
16
17impl<T: Identify> Default for Graph<T> {
18    fn default() -> Self {
19        Self {
20            nodes: Default::default(),
21        }
22    }
23}
24
25impl<T> FromIterator<T> for Graph<T>
26where
27    T: Identify,
28    T::Id: Ord + Clone,
29{
30    /// Returns the [`Graph`] resulting from all the nodes in the given iterator.
31    ///
32    /// This method does not check if there are repeated ids. In front of collisions
33    /// only the latest node will remain.
34    fn from_iter<V: IntoIterator<Item = T>>(nodes: V) -> Self {
35        Self {
36            nodes: BTreeMap::from_iter(nodes.into_iter().map(|node| (node.id().clone(), node))),
37        }
38    }
39}
40
41impl<T> Graph<T>
42where
43    T: Identify,
44    T::Id: Ord + Clone,
45{
46    /// Inserts the given node into the graph, overwriting any previous value with the same id.
47    pub fn with_node(mut self, node: T) -> Self {
48        self.nodes.insert(node.id().clone(), node);
49        self
50    }
51
52    /// Inserts the given node into the graph, returning the previous node with that same id, if any.
53    pub fn insert(&mut self, node: T) -> Option<T> {
54        self.nodes.insert(node.id().clone(), node)
55    }
56}
57
58impl<T> Graph<T>
59where
60    T: Identify,
61    T::Id: Ord,
62{
63    /// Removes the node with the given id from the graph, returning it, if any.
64    pub fn remove(&mut self, node_id: &T::Id) -> Option<T> {
65        self.nodes.remove(node_id)
66    }
67}
68
69impl<T: Identify> Graph<T> {
70    /// Returns the [`NodeProxy`] for the given id.
71    pub fn node(&self, id: T::Id) -> NodeProxy<'_, T> {
72        NodeProxy { graph: self, id }
73    }
74}
75
76#[cfg(any(test, feature = "fixtures"))]
77pub mod fixtures {
78    use crate::{id::Identify, resource::Resource};
79
80    /// A fake node type.
81    #[derive(Debug, Default)]
82    pub struct FakeNode<Id> {
83        pub id: Option<Id>,
84        pub edges: Option<Vec<Id>>,
85    }
86
87    impl<Id> Identify for FakeNode<Id> {
88        type Id = Id;
89
90        fn id(&self) -> &Self::Id {
91            self.id.as_ref().expect("id should be set")
92        }
93    }
94
95    impl<Id> FakeNode<Id> {
96        pub fn with_id(mut self, id: Id) -> Self {
97            self.id = Some(id);
98            self
99        }
100
101        pub fn with_edges(mut self, edges: Vec<Id>) -> Self {
102            self.edges = Some(edges);
103            self
104        }
105    }
106
107    /// A fake edge type.
108    pub struct FakeEdge<T> {
109        pub id: T,
110    }
111
112    impl<T> From<T> for FakeEdge<T> {
113        fn from(id: T) -> Self {
114            FakeEdge { id }
115        }
116    }
117
118    impl<T> Resource<FakeNode<T>> for FakeEdge<T>
119    where
120        T: Copy,
121    {
122        fn all(source: &FakeNode<T>) -> Vec<Self>
123        where
124            Self: Sized,
125        {
126            source
127                .edges
128                .as_ref()
129                .expect("edges method should be set")
130                .iter()
131                .cloned()
132                .map(FakeEdge::from)
133                .collect()
134        }
135    }
136
137    impl<T> Identify for FakeEdge<T> {
138        type Id = T;
139
140        fn id(&self) -> &Self::Id {
141            &self.id
142        }
143    }
144
145    #[allow(unused_macros)]
146    macro_rules! fake_node {
147        ($id:tt $(,$edges:tt)*) => {
148            FakeNode::default()
149                .with_id($id)
150                .with_edges(vec![$($edges)*])
151        };
152    }
153
154    #[allow(unused_imports)]
155    pub(crate) use fake_node;
156}