1use crate::identify::{Identifiable, Identity};
18
19use std::collections::HashMap;
20use std::fmt::Display;
21use std::marker::PhantomData;
22use std::rc::Rc;
23
24pub trait Query<I, V>
29where
30 I: Identity,
31 V: Identifiable<I>,
32{
33 fn query(&self, identifier: &I) -> Option<&V>;
34
35 fn all(&self) -> Vec<&V>;
36
37 fn create_index(&self) -> HashMap<I, Link<I, V>> {
38 let mut map: HashMap<_, _> = Default::default();
39 let values = self.all();
40 for value in values {
41 map.insert(value.get_id(), Link::Value(value));
42 }
43 map
44 }
45}
46
47impl<'a, I, V, T> Query<I, V> for &'a T
48where
49 T: Query<I, V>,
50 I: Identity,
51 V: Identifiable<I>,
52{
53 fn query(&self, identifier: &I) -> Option<&V> {
54 T::query(self, identifier)
55 }
56 fn all(&self) -> Vec<&V> {
57 T::all(self)
58 }
59}
60
61pub struct Edge<I: Identity, Meta> {
62 pub source: I,
63 pub sink: I,
64 pub order: usize,
65 pub meta: Rc<Meta>,
66}
67
68impl<I: Identity, M> Clone for Edge<I, M> {
69 fn clone(&self) -> Self {
70 Self {
71 source: self.source.clone(),
72 sink: self.sink.clone(),
73 order: self.order,
74 meta: Rc::clone(&self.meta),
75 }
76 }
77}
78
79impl<I, M> Edge<I, M>
80where
81 I: Identity,
82{
83 pub fn new(source: I, sink: I, order: usize, meta: M) -> Self {
84 Self {
85 source,
86 sink,
87 order,
88 meta: Rc::new(meta),
89 }
90 }
91}
92
93pub trait Edges<I, D>
99where
100 I: Identity,
101{
102 fn next_edge(&self, previous_edge_index: Option<usize>) -> Option<Edge<I, D>>;
103 fn edges(&self) -> EdgeIterator<'_, I, D, Self>
104 where
105 Self: Sized,
106 {
107 EdgeIterator {
108 last_edge_index: None,
109 node_meta: Default::default(),
110 edges: &self,
111 }
112 }
113}
114
115pub trait ExtractData<D: 'static> {
116 fn extract_data(&self) -> D;
117}
118
119impl<T> ExtractData<()> for T {
120 fn extract_data(&self) {}
121}
122
123macro_rules! extract_data_impl {
124 ($(($($tup:tt), +)) +) => {
125 $(
126 impl <T, $($tup),+> ExtractData<($($tup),+)> for T
127 where
128 $(T: ExtractData<$tup>), *,
129 $($tup: 'static), *
130
131 {
132 fn extract_data(&self) -> ($($tup),+) {
133 ( $(<Self as ExtractData<$tup>>::extract_data(&self)), * )
134 }
135 }
136 )+
137 }
138}
139
140extract_data_impl! {
141 (D1, D2)
142 (D1, D2, D3)
143 (D1, D2, D3, D4)
144 (D1, D2, D3, D4, D5)
145 (D1, D2, D3, D4, D5, D6)
146 (D1, D2, D3, D4, D5, D6, D7)
147 (D1, D2, D3, D4, D5, D6, D7, D8)
148 (D1, D2, D3, D4, D5, D6, D7, D8, D9)
149 (D1, D2, D3, D4, D5, D6, D7, D8, D9, D10)
150}
151
152pub trait Label {
182 type Label: Display + Clone;
183 fn label(&self) -> Self::Label;
184}
185
186pub struct EdgeIterator<'a, I: Identity, E, ED>
187where
188 ED: Edges<I, E>,
189{
190 last_edge_index: Option<usize>,
191 node_meta: PhantomData<(I, E)>,
192 edges: &'a ED,
193}
194
195impl<'a, I, E, Ed> Iterator for EdgeIterator<'a, I, E, Ed>
196where
197 I: Identity,
198 Ed: Edges<I, E>,
199{
200 type Item = Edge<I, E>;
201 fn next(&mut self) -> Option<Self::Item> {
202 let next = self.edges.next_edge(self.last_edge_index.take())?;
203 self.last_edge_index = Some(next.order);
204 Some(next)
205 }
206}
207
208pub enum Link<'a, I, V> {
209 Link(I),
210 Value(&'a V),
211}
212
213impl<'a, I, V> Query<I, V> for HashMap<I, Link<'a, I, V>>
214where
215 I: Identity,
216 V: Identifiable<I>,
217{
218 fn query(&self, identifier: &I) -> Option<&V> {
219 let mut current = self.get(identifier)?;
220
221 loop {
222 match current {
223 Link::Link(follow) => {
224 current = self.get(follow).expect("Unable to follow link in index");
225 }
226 Link::Value(output) => return Some(output),
227 }
228 }
229 }
230
231 fn all(&self) -> Vec<&V> {
232 self.values()
233 .filter_map(|value| match value {
234 Link::Link(_) => None,
235 Link::Value(v) => Some(*v),
236 })
237 .collect()
238 }
239}