1use crate::ElementId;
2use crate::graph::Graph;
3use crate::walker::builder::{EdgeWalkerBuilder, StartWalkerBuilder, VertexWalkerBuilder};
4use crate::walker::steps::Empty;
5use crate::walker::{EdgeWalker, VertexWalker, Walker};
6use include_doc::function_body;
7use std::marker::PhantomData;
8use std::ops::{Deref, DerefMut};
9#[derive(Clone, Debug)]
12pub struct ContextRef<Current, Parent> {
13 inner: Inner<Current, Parent>,
14}
15
16#[derive(Debug, Clone)]
17struct Inner<Current, Parent> {
18 parent: Parent,
19 delegate: Current,
20}
21
22impl<Current, Parent> Deref for ContextRef<Current, Parent> {
23 type Target = Current;
24
25 fn deref(&self) -> &Self::Target {
26 &self.inner.delegate
27 }
28}
29
30impl<Current, Parent> DerefMut for ContextRef<Current, Parent> {
31 fn deref_mut(&mut self) -> &mut Self::Target {
32 &mut self.inner.delegate
33 }
34}
35
36impl<Current, Parent> ContextRef<Current, Parent> {
37 pub(crate) fn new(delegate: Current, parent: Parent) -> ContextRef<Current, Parent> {
38 Self {
39 inner: Inner { parent, delegate },
40 }
41 }
42 pub fn parent(&self) -> &Parent {
43 &self.inner.parent
44 }
45}
46
47#[derive(Clone, Debug)]
48pub struct DefaultVertexContext<VertexId, Vertex> {
49 pub(crate) vertex_id: VertexId,
50 pub(crate) vertex: Vertex,
51}
52
53impl<VertexId, Vertex> DefaultVertexContext<VertexId, Vertex> {
54 pub fn vertex(&self) -> &Vertex {
55 &self.vertex
56 }
57
58 pub fn vertex_id(&self) -> &VertexId {
59 &self.vertex_id
60 }
61}
62
63#[derive(Clone, Debug)]
64pub struct DefaultEdgeContext<EdgeId, Edge> {
65 pub(crate) edge_id: EdgeId,
66 pub(crate) edge: Edge,
67}
68
69impl<EdgeId, Edge> DefaultEdgeContext<EdgeId, Edge> {
70 pub fn edge(&self) -> &Edge {
71 &self.edge
72 }
73
74 pub fn edge_id(&self) -> &EdgeId {
75 &self.edge_id
76 }
77}
78
79pub struct VertexContext<'graph, Parent, Callback, Context>
80where
81 Parent: VertexWalker<'graph>,
82 Callback: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
83{
84 _phantom_data: PhantomData<&'graph ()>,
85 parent: Parent,
86 callback: Callback,
87 context: Option<Context>,
88}
89
90impl<'graph, Parent, Callback, Context> VertexContext<'graph, Parent, Callback, Context>
91where
92 Parent: VertexWalker<'graph>,
93 Callback: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
94{
95 pub fn new(parent: Parent, callback: Callback) -> Self {
96 VertexContext {
97 _phantom_data: Default::default(),
98 parent,
99 callback,
100 context: None,
101 }
102 }
103}
104
105impl<'graph, Parent, Predicate, Context> Walker<'graph>
106 for VertexContext<'graph, Parent, Predicate, Context>
107where
108 Parent: VertexWalker<'graph>,
109 Predicate: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
110 Context: Clone + 'static,
111{
112 type Graph = Parent::Graph;
113 type Context = Context;
114
115 fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
116 self.next(graph).map(ElementId::Vertex)
117 }
118
119 fn ctx(&self) -> &Self::Context {
120 self.context
121 .as_ref()
122 .expect("context cannot be retrieved before call to next")
123 }
124
125 fn ctx_mut(&mut self) -> &mut Self::Context {
126 self.context
127 .as_mut()
128 .expect("context cannot be retrieved before call to next")
129 }
130}
131
132impl<'graph, Parent, Predicate, Context> VertexWalker<'graph>
133 for VertexContext<'graph, Parent, Predicate, Context>
134where
135 Parent: VertexWalker<'graph>,
136 Predicate: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
137 Context: Clone + 'static,
138{
139 fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::VertexId> {
140 while let Some(next) = self.parent.next(graph) {
141 if let Some(vertex) = graph.vertex(next) {
142 self.context = Some((self.callback)(&vertex, self.parent.ctx()));
143 return Some(next);
144 }
145 }
146 None
147 }
148}
149
150pub struct EdgeContext<'graph, Parent, Callback, Context>
151where
152 Parent: EdgeWalker<'graph>,
153 Callback: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
154{
155 _phantom_data: PhantomData<&'graph ()>,
156 parent: Parent,
157 callback: Callback,
158 context: Option<Context>,
159}
160
161impl<'graph, Parent, Callback, Context> EdgeContext<'graph, Parent, Callback, Context>
162where
163 Parent: EdgeWalker<'graph>,
164 Callback: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
165{
166 pub fn new(parent: Parent, callback: Callback) -> Self {
167 EdgeContext {
168 _phantom_data: Default::default(),
169 parent,
170 callback,
171 context: None,
172 }
173 }
174}
175
176impl<'graph, Parent, Predicate, Context> Walker<'graph>
177 for EdgeContext<'graph, Parent, Predicate, Context>
178where
179 Parent: EdgeWalker<'graph>,
180 Predicate: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
181 Context: Clone + 'static,
182{
183 type Graph = Parent::Graph;
184
185 type Context = Context;
186
187 fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
188 self.next(graph).map(ElementId::Edge)
189 }
190 fn ctx(&self) -> &Self::Context {
191 self.context
192 .as_ref()
193 .expect("context cannot be retrieved before call to next")
194 }
195
196 fn ctx_mut(&mut self) -> &mut Self::Context {
197 self.context
198 .as_mut()
199 .expect("context cannot be retrieved before call to next")
200 }
201}
202
203impl<'graph, Parent, Predicate, Context> EdgeWalker<'graph>
204 for EdgeContext<'graph, Parent, Predicate, Context>
205where
206 Parent: EdgeWalker<'graph>,
207 Predicate: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
208 Context: Clone + 'static,
209{
210 fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::EdgeId> {
211 if let Some(next) = self.parent.next(graph) {
212 if let Some(edge) = graph.edge(next) {
213 self.context = Some((self.callback)(&edge, self.parent.ctx()));
214 return Some(next);
215 }
216 }
217 None
218 }
219}
220
221impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
222where
223 Graph: crate::graph::Graph,
224 Walker: VertexWalker<'graph, Graph = Graph>,
225{
226 #[doc = function_body!("examples/context.rs", vertex_context_example, [])]
266 pub fn push_context<Callback, Context>(
278 self,
279 callback: Callback,
280 ) -> VertexWalkerBuilder<
281 'graph,
282 Mutability,
283 Graph,
284 VertexContext<
285 'graph,
286 Walker,
287 impl Fn(
288 &Graph::VertexReference<'_>,
289 &Walker::Context,
290 ) -> ContextRef<Context, Walker::Context>,
291 ContextRef<Context, Walker::Context>,
292 >,
293 >
294 where
295 Callback: Fn(&Graph::VertexReference<'_>, &Walker::Context) -> Context + 'graph,
296 Context: Clone + 'static,
297 {
298 self.with_vertex_walker(move |walker| {
299 walker.context(move |vertex, context| {
300 ContextRef::new(callback(vertex, context), context.clone())
301 })
302 })
303 }
304}
305
306impl<'graph, Mutability, Graph, Walker> EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
307where
308 Graph: crate::graph::Graph,
309 Walker: EdgeWalker<'graph, Graph = Graph>,
310 <Walker as crate::walker::Walker<'graph>>::Context: Clone + 'static,
311{
312 #[doc = function_body!("examples/context.rs", edge_context_example, [])]
354 pub fn push_context<Callback, Context>(
365 self,
366 callback: Callback,
367 ) -> EdgeWalkerBuilder<
368 'graph,
369 Mutability,
370 Graph,
371 EdgeContext<
372 'graph,
373 Walker,
374 impl Fn(&Graph::EdgeReference<'_>, &Walker::Context) -> ContextRef<Context, Walker::Context>,
375 ContextRef<Context, Walker::Context>,
376 >,
377 >
378 where
379 Callback: Fn(&Graph::EdgeReference<'_>, &Walker::Context) -> Context,
380 Context: Clone + 'static,
381 {
382 self.with_edge_walker(move |walker| {
383 walker.context(move |edge, context| {
384 ContextRef::new(callback(edge, context), context.clone())
385 })
386 })
387 }
388}
389
390impl<'graph, Graph, Mutability> StartWalkerBuilder<'graph, Mutability, Graph, ()>
391where
392 Graph: crate::graph::Graph,
393{
394 pub fn push_context<Context>(
395 self,
396 context: Context,
397 ) -> StartWalkerBuilder<'graph, Mutability, Graph, Context>
398 where
399 Context: Clone + 'static,
400 {
401 StartWalkerBuilder {
402 _phantom: Default::default(),
403 graph: self.graph,
404 empty: Empty::with_context(context),
405 }
406 }
407}