From 6896b9e4347dc8fe9945f7c7ef78cf2459e0391b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Nevyho=C5=A1t=C4=9Bn=C3=BD?= Date: Thu, 8 Aug 2024 09:52:19 +0200 Subject: [PATCH] Implement core traits for graph references Ideally, an automatic mechanism would be used like implemented by the auto_impl crate. However, at this moment, gryf runs into https://github.com/auto-impl-rs/auto_impl/issues/87 --- gryf/src/core/graph.rs | 223 ++++++++++++++++++++++++++++++++++------- gryf/src/core/props.rs | 39 +++++++ gryf/src/lib.rs | 71 ++++++++++++- 3 files changed, 297 insertions(+), 36 deletions(-) diff --git a/gryf/src/core/graph.rs b/gryf/src/core/graph.rs index 0e05c02..46b0ea7 100644 --- a/gryf/src/core/graph.rs +++ b/gryf/src/core/graph.rs @@ -313,58 +313,51 @@ mod imp { use super::*; - impl GraphBase for &G + impl GraphIdTypes for G where - G: GraphBase + ?Sized, + G: GraphBase, { type VertexId = G::VertexId; type EdgeId = G::EdgeId; - type EdgeType = G::EdgeType; - - fn vertex_count_hint(&self) -> Option { - (**self).vertex_count_hint() - } - - fn edge_count_hint(&self) -> Option { - (**self).edge_count_hint() - } } - impl GraphBase for &mut G + impl GraphWeak for G where - G: GraphBase + ?Sized, + G: GraphRef, { - type VertexId = G::VertexId; - type EdgeId = G::EdgeId; - type EdgeType = G::EdgeType; - - fn vertex_count_hint(&self) -> Option { - (**self).vertex_count_hint() + fn vertex_weak(&self, id: &Self::VertexId) -> Option> { + self.vertex(id).map(WeakRef::Borrowed) } - fn edge_count_hint(&self) -> Option { - (**self).edge_count_hint() + fn edge_weak(&self, id: &Self::EdgeId) -> Option> { + self.edge(id).map(WeakRef::Borrowed) } } - impl GraphIdTypes for G - where - G: GraphBase, - { - type VertexId = G::VertexId; - type EdgeId = G::EdgeId; - } + macro_rules! deref_graph_base { + ($($ref_kind:tt)*) => { + impl GraphBase for $($ref_kind)* G + where + G: GraphBase + ?Sized, + { + type VertexId = G::VertexId; + type EdgeId = G::EdgeId; + type EdgeType = G::EdgeType; - impl> GraphWeak for G { - fn vertex_weak(&self, id: &Self::VertexId) -> Option> { - self.vertex(id).map(WeakRef::Borrowed) - } + fn vertex_count_hint(&self) -> Option { + (**self).vertex_count_hint() + } - fn edge_weak(&self, id: &Self::EdgeId) -> Option> { - self.edge(id).map(WeakRef::Borrowed) + fn edge_count_hint(&self) -> Option { + (**self).edge_count_hint() + } + } } } + deref_graph_base!(&); + deref_graph_base!(&mut); + macro_rules! deref_neighbors { ($($ref_kind:tt)*) => { impl Neighbors for $($ref_kind)* G @@ -500,4 +493,166 @@ mod imp { deref_edge_set!(&); deref_edge_set!(&mut); + + macro_rules! deref_graph_ref { + ($($ref_kind:tt)*) => { + impl GraphRef for $($ref_kind)* G + where + G: GraphRef, + { + type VertexRef<'a> = G::VertexRef<'a> + where + Self: 'a, + V: 'a; + + type VerticesIter<'a> = G::VerticesIter<'a> + where + Self: 'a, + V: 'a; + + type EdgeRef<'a> = G::EdgeRef<'a> + where + Self: 'a, + E: 'a; + + type EdgesIter<'a> = G::EdgesIter<'a> + where + Self: 'a, + E: 'a; + + fn vertices(&self) -> Self::VerticesIter<'_> { + (**self).vertices() + } + + fn edges(&self) -> Self::EdgesIter<'_> { + (**self).edges() + } + + fn vertex(&self, id: &Self::VertexId) -> Option<&V> { + (**self).vertex(id) + } + + fn edge(&self, id: &Self::EdgeId) -> Option<&E> { + (**self).edge(id) + } + + fn find_vertex(&self, vertex: &V) -> Option + where + V: Eq, + { + (**self).find_vertex(vertex) + } + } + } + } + + deref_graph_ref!(&); + deref_graph_ref!(&mut); + + impl GraphMut for &mut G + where + G: GraphMut, + { + fn vertex_mut(&mut self, id: &Self::VertexId) -> Option<&mut V> { + (**self).vertex_mut(id) + } + + fn edge_mut(&mut self, id: &Self::EdgeId) -> Option<&mut E> { + (**self).edge_mut(id) + } + + fn try_replace_vertex( + &mut self, + id: &Self::VertexId, + vertex: V, + ) -> Result> { + (**self).try_replace_vertex(id, vertex) + } + + fn replace_vertex(&mut self, id: &Self::VertexId, vertex: V) -> V { + (**self).replace_vertex(id, vertex) + } + + fn try_replace_edge( + &mut self, + id: &Self::EdgeId, + edge: E, + ) -> Result> { + (**self).try_replace_edge(id, edge) + } + + fn replace_edge(&mut self, id: &Self::EdgeId, edge: E) -> E { + (**self).replace_edge(id, edge) + } + } + + impl GraphAdd for &mut G + where + G: GraphAdd, + { + fn try_add_vertex(&mut self, vertex: V) -> Result> { + (**self).try_add_vertex(vertex) + } + + fn try_add_edge( + &mut self, + src: &Self::VertexId, + dst: &Self::VertexId, + edge: E, + ) -> Result> { + (**self).try_add_edge(src, dst, edge) + } + + fn add_vertex(&mut self, vertex: V) -> Self::VertexId { + (**self).add_vertex(vertex) + } + + fn try_get_or_add_vertex(&mut self, vertex: V) -> Result> + where + V: Eq, + { + (**self).try_get_or_add_vertex(vertex) + } + + fn get_or_add_vertex(&mut self, vertex: V) -> Self::VertexId + where + V: Eq, + { + (**self).get_or_add_vertex(vertex) + } + + fn add_edge( + &mut self, + src: &Self::VertexId, + dst: &Self::VertexId, + edge: E, + ) -> Self::EdgeId { + (**self).add_edge(src, dst, edge) + } + } + + impl GraphFull for &mut G + where + G: GraphFull, + { + fn remove_vertex(&mut self, id: &Self::VertexId) -> Option { + (**self).remove_vertex(id) + } + + fn remove_edge(&mut self, id: &Self::EdgeId) -> Option { + (**self).remove_edge(id) + } + + fn clear(&mut self) { + (**self).clear() + } + + fn remove_edge_between(&mut self, src: &Self::VertexId, dst: &Self::VertexId) -> Option { + (**self).remove_edge_between(src, dst) + } + + fn clear_edges(&mut self) { + (**self).clear_edges() + } + } } diff --git a/gryf/src/core/props.rs b/gryf/src/core/props.rs index e72f676..c2a2941 100644 --- a/gryf/src/core/props.rs +++ b/gryf/src/core/props.rs @@ -67,3 +67,42 @@ mod private { impl Sealed for NoReplace {} impl Sealed for ReplaceRemoved {} } + +mod imp { + use super::{Guarantee, MultiEdge}; + + impl MultiEdge for &G where G: MultiEdge {} + impl MultiEdge for &mut G where G: MultiEdge {} + + macro_rules! deref_guarantee { + ($($ref_kind:tt)*) => { + impl Guarantee for $($ref_kind)* G + where + G: Guarantee, + { + fn is_loop_free() -> bool { + G::is_loop_free() + } + + fn has_paths_only() -> bool { + G::has_paths_only() + } + + fn has_trees_only() -> bool { + G::has_trees_only() + } + + fn has_bipartite_only() -> bool { + G::has_bipartite_only() + } + + fn is_connected() -> bool { + G::is_connected() + } + } + } + } + + deref_guarantee!(&); + deref_guarantee!(&mut ); +} diff --git a/gryf/src/lib.rs b/gryf/src/lib.rs index 2a67c86..f10fbe9 100644 --- a/gryf/src/lib.rs +++ b/gryf/src/lib.rs @@ -25,12 +25,19 @@ mod tests { use gryf_derive::*; use crate::{ - core::{id::DefaultId, marker::Directed}, + core::{ + id::DefaultId, + marker::Directed, + props::{Guarantee, MultiEdge}, + EdgeSet, GraphAdd, GraphBase, GraphFull, GraphMut, GraphRef, GraphWeak, Neighbors, + VertexSet, + }, storage::AdjList, }; // Test hygiene of the custom derive macros. #[derive( + Clone, GraphBase, Neighbors, VertexSet, @@ -43,8 +50,68 @@ mod tests { Guarantee, )] #[gryf_crate] - struct TestWrapper1 { + struct TestWrapper { #[graph] graph: AdjList<(), (), Directed, DefaultId>, } + + fn require_graph_base(_: impl GraphBase) {} + fn require_neighbors(_: impl Neighbors) {} + fn require_vertex_set(_: impl VertexSet) {} + fn require_edge_set(_: impl EdgeSet) {} + fn require_graph_ref(_: impl GraphRef<(), ()>) {} + fn require_graph_weak(_: impl GraphWeak<(), ()>) {} + fn require_graph_mut(_: impl GraphMut<(), ()>) {} + fn require_graph_add(_: impl GraphAdd<(), ()>) {} + fn require_graph_full(_: impl GraphFull<(), ()>) {} + fn require_multi_edge(_: impl MultiEdge) {} + fn require_guarantee(_: impl Guarantee) {} + + #[test] + fn trait_impl() { + let mut g = TestWrapper { + graph: AdjList::default(), + }; + + require_graph_base(g.clone()); + require_graph_base(&g); + require_graph_base(&mut g); + + require_neighbors(g.clone()); + require_neighbors(&g); + require_neighbors(&mut g); + + require_vertex_set(g.clone()); + require_vertex_set(&g); + require_vertex_set(&mut g); + + require_edge_set(g.clone()); + require_edge_set(&g); + require_edge_set(&mut g); + + require_graph_ref(g.clone()); + require_graph_ref(&g); + require_graph_ref(&mut g); + + require_graph_weak(g.clone()); + require_graph_weak(&g); + require_graph_weak(&mut g); + + require_graph_mut(g.clone()); + require_graph_mut(&mut g); + + require_graph_add(g.clone()); + require_graph_add(&mut g); + + require_graph_full(g.clone()); + require_graph_full(&mut g); + + require_multi_edge(g.clone()); + require_multi_edge(&g); + require_multi_edge(&mut g); + + require_guarantee(g.clone()); + require_guarantee(&g); + require_guarantee(&mut g); + } }