use crate::ElementId;
use crate::graph::Graph;
use crate::walker::builder::{EdgeWalkerBuilder, StartWalkerBuilder, VertexWalkerBuilder};
use crate::walker::steps::Empty;
use crate::walker::{EdgeWalker, VertexWalker, Walker};
use include_doc::function_body;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
#[derive(Clone, Debug)]
pub struct ContextRef<Current, Parent> {
inner: Inner<Current, Parent>,
}
#[derive(Debug, Clone)]
struct Inner<Current, Parent> {
parent: Parent,
delegate: Current,
}
impl<Current, Parent> Deref for ContextRef<Current, Parent> {
type Target = Current;
fn deref(&self) -> &Self::Target {
&self.inner.delegate
}
}
impl<Current, Parent> DerefMut for ContextRef<Current, Parent> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner.delegate
}
}
impl<Current, Parent> ContextRef<Current, Parent> {
pub(crate) fn new(delegate: Current, parent: Parent) -> ContextRef<Current, Parent> {
Self {
inner: Inner { parent, delegate },
}
}
pub fn parent(&self) -> &Parent {
&self.inner.parent
}
}
#[derive(Clone, Debug)]
pub struct DefaultVertexContext<VertexId, Vertex> {
pub(crate) vertex_id: VertexId,
pub(crate) vertex: Vertex,
}
impl<VertexId, Vertex> DefaultVertexContext<VertexId, Vertex> {
pub fn vertex(&self) -> &Vertex {
&self.vertex
}
pub fn vertex_id(&self) -> &VertexId {
&self.vertex_id
}
}
#[derive(Clone, Debug)]
pub struct DefaultEdgeContext<EdgeId, Edge> {
pub(crate) edge_id: EdgeId,
pub(crate) edge: Edge,
}
impl<EdgeId, Edge> DefaultEdgeContext<EdgeId, Edge> {
pub fn edge(&self) -> &Edge {
&self.edge
}
pub fn edge_id(&self) -> &EdgeId {
&self.edge_id
}
}
pub struct VertexContext<'graph, Parent, Callback, Context>
where
Parent: VertexWalker<'graph>,
Callback: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
{
_phantom_data: PhantomData<&'graph ()>,
parent: Parent,
callback: Callback,
context: Option<Context>,
}
impl<'graph, Parent, Callback, Context> VertexContext<'graph, Parent, Callback, Context>
where
Parent: VertexWalker<'graph>,
Callback: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
{
pub fn new(parent: Parent, callback: Callback) -> Self {
VertexContext {
_phantom_data: Default::default(),
parent,
callback,
context: None,
}
}
}
impl<'graph, Parent, Predicate, Context> Walker<'graph>
for VertexContext<'graph, Parent, Predicate, Context>
where
Parent: VertexWalker<'graph>,
Predicate: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
Context: Clone + 'static,
{
type Graph = Parent::Graph;
type Context = Context;
fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
self.next(graph).map(ElementId::Vertex)
}
fn ctx(&self) -> &Self::Context {
self.context
.as_ref()
.expect("context cannot be retrieved before call to next")
}
fn ctx_mut(&mut self) -> &mut Self::Context {
self.context
.as_mut()
.expect("context cannot be retrieved before call to next")
}
}
impl<'graph, Parent, Predicate, Context> VertexWalker<'graph>
for VertexContext<'graph, Parent, Predicate, Context>
where
Parent: VertexWalker<'graph>,
Predicate: Fn(&<Parent::Graph as Graph>::VertexReference<'_>, &Parent::Context) -> Context,
Context: Clone + 'static,
{
fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::VertexId> {
while let Some(next) = self.parent.next(graph) {
if let Some(vertex) = graph.vertex(next) {
self.context = Some((self.callback)(&vertex, self.parent.ctx()));
return Some(next);
}
}
None
}
}
pub struct EdgeContext<'graph, Parent, Callback, Context>
where
Parent: EdgeWalker<'graph>,
Callback: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
{
_phantom_data: PhantomData<&'graph ()>,
parent: Parent,
callback: Callback,
context: Option<Context>,
}
impl<'graph, Parent, Callback, Context> EdgeContext<'graph, Parent, Callback, Context>
where
Parent: EdgeWalker<'graph>,
Callback: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
{
pub fn new(parent: Parent, callback: Callback) -> Self {
EdgeContext {
_phantom_data: Default::default(),
parent,
callback,
context: None,
}
}
}
impl<'graph, Parent, Predicate, Context> Walker<'graph>
for EdgeContext<'graph, Parent, Predicate, Context>
where
Parent: EdgeWalker<'graph>,
Predicate: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
Context: Clone + 'static,
{
type Graph = Parent::Graph;
type Context = Context;
fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
self.next(graph).map(ElementId::Edge)
}
fn ctx(&self) -> &Self::Context {
self.context
.as_ref()
.expect("context cannot be retrieved before call to next")
}
fn ctx_mut(&mut self) -> &mut Self::Context {
self.context
.as_mut()
.expect("context cannot be retrieved before call to next")
}
}
impl<'graph, Parent, Predicate, Context> EdgeWalker<'graph>
for EdgeContext<'graph, Parent, Predicate, Context>
where
Parent: EdgeWalker<'graph>,
Predicate: Fn(&<Parent::Graph as Graph>::EdgeReference<'_>, &Parent::Context) -> Context,
Context: Clone + 'static,
{
fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::EdgeId> {
if let Some(next) = self.parent.next(graph) {
if let Some(edge) = graph.edge(next) {
self.context = Some((self.callback)(&edge, self.parent.ctx()));
return Some(next);
}
}
None
}
}
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
where
Graph: crate::graph::Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
{
#[doc = function_body!("examples/context.rs", vertex_context_example, [])]
pub fn push_context<Callback, Context>(
self,
callback: Callback,
) -> VertexWalkerBuilder<
'graph,
Mutability,
Graph,
VertexContext<
'graph,
Walker,
impl Fn(
&Graph::VertexReference<'_>,
&Walker::Context,
) -> ContextRef<Context, Walker::Context>,
ContextRef<Context, Walker::Context>,
>,
>
where
Callback: Fn(&Graph::VertexReference<'_>, &Walker::Context) -> Context + 'graph,
Context: Clone + 'static,
{
self.with_vertex_walker(move |walker| {
walker.context(move |vertex, context| {
ContextRef::new(callback(vertex, context), context.clone())
})
})
}
}
impl<'graph, Mutability, Graph, Walker> EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
where
Graph: crate::graph::Graph,
Walker: EdgeWalker<'graph, Graph = Graph>,
<Walker as crate::walker::Walker<'graph>>::Context: Clone + 'static,
{
#[doc = function_body!("examples/context.rs", edge_context_example, [])]
pub fn push_context<Callback, Context>(
self,
callback: Callback,
) -> EdgeWalkerBuilder<
'graph,
Mutability,
Graph,
EdgeContext<
'graph,
Walker,
impl Fn(&Graph::EdgeReference<'_>, &Walker::Context) -> ContextRef<Context, Walker::Context>,
ContextRef<Context, Walker::Context>,
>,
>
where
Callback: Fn(&Graph::EdgeReference<'_>, &Walker::Context) -> Context,
Context: Clone + 'static,
{
self.with_edge_walker(move |walker| {
walker.context(move |edge, context| {
ContextRef::new(callback(edge, context), context.clone())
})
})
}
}
impl<'graph, Graph, Mutability> StartWalkerBuilder<'graph, Mutability, Graph, ()>
where
Graph: crate::graph::Graph,
{
pub fn push_context<Context>(
self,
context: Context,
) -> StartWalkerBuilder<'graph, Mutability, Graph, Context>
where
Context: Clone + 'static,
{
StartWalkerBuilder {
_phantom: Default::default(),
graph: self.graph,
empty: Empty::with_context(context),
}
}
}