use crate::element::Element;
use crate::walker::builder::{ImmutableMarker, MutableMarker, StartWalkerBuilder};
use crate::{EdgeSearch, Value, walker};
use crate::{Label, VertexSearch};
use derivative::Derivative;
use std::fmt::Debug;
use std::hash::Hash;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord)]
#[repr(u8)]
pub enum Direction {
Outgoing,
Incoming,
#[default]
All,
}
impl Direction {
pub fn reverse(&self) -> Self {
match self {
Direction::Outgoing => Direction::Incoming,
Direction::Incoming => Direction::Outgoing,
Direction::All => Direction::All,
}
}
}
#[derive(Debug, Derivative)]
#[derivative(
Copy(bound = ""),
Clone(bound = ""),
Eq(bound = ""),
PartialEq(bound = ""),
Hash(bound = "")
)]
pub enum ElementId<Graph>
where
Graph: crate::Graph,
{
Vertex(Graph::VertexId),
Edge(Graph::EdgeId),
}
pub trait Graph: Sized + Debug {
type Vertex: Debug + Element;
type Edge: Debug + Element;
type VertexId: Debug + Eq + PartialEq + Copy + Clone + Hash + Into<ElementId<Self>> + 'static;
type EdgeId: Debug + Eq + PartialEq + Copy + Clone + Hash + Into<ElementId<Self>> + 'static;
type VertexReference<'graph>: VertexReference<'graph, Self>
where
Self: 'graph;
type VertexReferenceMut<'graph>: VertexReferenceMut<'graph, Self>
where
Self: 'graph;
type EdgeReference<'graph>: EdgeReference<'graph, Self>
where
Self: 'graph;
type EdgeReferenceMut<'graph>: EdgeReferenceMut<'graph, Self>
where
Self: 'graph;
type EdgeIter<'search, 'graph>: Iterator<Item = Self::EdgeReference<'graph>>
where
Self: 'graph;
type VertexIter<'search, 'graph>: Iterator<Item = Self::VertexReference<'graph>>
where
Self: 'graph;
fn add_vertex(&mut self, vertex: Self::Vertex) -> Self::VertexId;
fn add_edge(
&mut self,
from: Self::VertexId,
to: Self::VertexId,
edge: Self::Edge,
) -> Self::EdgeId;
fn vertex(&self, id: Self::VertexId) -> Option<Self::VertexReference<'_>>;
fn vertex_mut(&mut self, id: Self::VertexId) -> Option<Self::VertexReferenceMut<'_>>;
fn vertices<'search>(
&self,
vertex_search: &VertexSearch<'search, Self>,
) -> Self::VertexIter<'search, '_>;
fn edge(&self, id: Self::EdgeId) -> Option<Self::EdgeReference<'_>>;
fn edge_mut(&mut self, id: Self::EdgeId) -> Option<Self::EdgeReferenceMut<'_>>;
fn edges<'search>(
&self,
id: Self::VertexId,
search: &EdgeSearch<'search, Self>,
) -> Self::EdgeIter<'search, '_>;
fn clear(&mut self) {
panic!("This graph implementation does not support clearing")
}
fn dbg<T: Into<ElementId<Self>>>(&self, id: T) -> String {
match id.into() {
ElementId::Vertex(vertex_id) => self
.vertex(vertex_id)
.map_or_else(|| "<missing>".to_string(), |vertex| format!("{:?}", vertex)),
ElementId::Edge(edge_id) => self
.edge(edge_id)
.map_or_else(|| "<missing>".to_string(), |edge| format!("{:?}", edge)),
}
}
fn walk(&self) -> StartWalkerBuilder<ImmutableMarker, Self, ()>
where
Self: Sized,
{
walker::builder::new_start(self)
}
fn walk_mut(&mut self) -> StartWalkerBuilder<MutableMarker, Self, ()>
where
Self: Sized,
{
walker::builder::new_start_mut(self)
}
}
pub trait VertexReference<'graph, Graph>: Debug
where
Graph: crate::Graph,
{
fn id(&self) -> Graph::VertexId;
fn weight(&self) -> &Graph::Vertex;
fn project<'reference, T: Project<'reference, <Graph as crate::Graph>::Vertex>>(
&'reference self,
) -> Option<T>;
}
pub trait VertexReferenceMut<'graph, Graph>: VertexReference<'graph, Graph>
where
Graph: crate::graph::Graph + 'graph,
{
type MutationListener<'reference>: MutationListener<'reference, Graph::Vertex>;
fn weight_mut(&mut self) -> &mut Graph::Vertex;
fn project_mut<
'reference,
T: ProjectMut<'reference, <Graph as crate::Graph>::Vertex, Self::MutationListener<'reference>>,
>(
&'reference mut self,
) -> Option<T>;
}
pub trait EdgeReference<'graph, Graph>: Debug
where
Graph: crate::graph::Graph,
{
fn id(&self) -> Graph::EdgeId;
fn tail(&self) -> Graph::VertexId;
fn head(&self) -> Graph::VertexId;
fn weight(&self) -> &Graph::Edge;
fn project<'reference, T: Project<'reference, <Graph as crate::Graph>::Edge>>(
&'reference self,
) -> Option<T>;
}
pub trait EdgeReferenceMut<'graph, Graph>: EdgeReference<'graph, Graph>
where
Graph: crate::Graph,
{
type MutationListener<'reference>: MutationListener<'reference, Graph::Edge>;
fn weight_mut(&mut self) -> &mut Graph::Edge;
fn project_mut<
'reference,
T: ProjectMut<'reference, <Graph as crate::Graph>::Edge, Self::MutationListener<'reference>>,
>(
&'reference mut self,
) -> Option<T>;
}
pub trait Project<'reference, Weight>
where
Weight: Element,
Self: Sized,
{
fn project(weight: &'reference Weight) -> Option<Self>;
}
pub trait ProjectMut<'reference, Weight, MutationListener>
where
Weight: Element,
MutationListener: crate::MutationListener<'reference, Weight>,
Self: Sized,
{
fn project_mut(
weight: &'reference mut Weight,
mutation_listener: MutationListener,
) -> Option<Self>;
}
pub trait MutationListener<'reference, Element>
where
Element: crate::Element,
{
fn update(&mut self, index: <Element::Label as Label>::Index, before: Value, after: Value);
}
impl<Element> MutationListener<'_, Element> for ()
where
Element: crate::Element,
{
fn update(&mut self, _index: <Element::Label as Label>::Index, _before: Value, _after: Value) {}
}