1use std::collections::BTreeMap;
4
5use crate::id::Identify;
6
7mod proxy;
8pub use proxy::*;
9
10#[derive(Debug)]
12pub struct Graph<T: Identify> {
13 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 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 pub fn with_node(mut self, node: T) -> Self {
48 self.nodes.insert(node.id().clone(), node);
49 self
50 }
51
52 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 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 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 #[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 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}