diff --git a/src/generators.rs b/src/generators.rs index 4457fea..5dc36e7 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -1,6 +1,48 @@ //! Generators for common graphs. -use crate::traits::{GraphTopology, GraphTopologyAddition}; +use crate::models::AppendGraph; +use crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyConversion}; + +/// Builds a graph of type `G` by running a generator on a temporary [`AppendGraph`]. +/// +/// `generate_as` fills a temporary graph and converts it to `G`. It returns the handles of the +/// elements it created as handles of the resulting graph. This makes it possible to obtain graph +/// types directly that do not implement [`GraphTopologyAddition`], such as [`FrozenGraph`]. +/// +/// # Examples +/// +/// ``` +/// use grapherity::generators; +/// use grapherity::models::FrozenGraph; +/// use grapherity::traits::GraphTopology; +/// +/// let (graph, vertices, edges) = generators::generate_as::(generators::petersen); +/// assert_eq!(graph.vertex_count(), 10); +/// assert_eq!(graph.edge_count(), 15); +/// assert!(graph.vertices().all(|v| graph.degree(v) == 3)); +/// ``` +/// +/// [`FrozenGraph`]: crate::models::FrozenGraph +pub fn generate_as( + generator: impl FnOnce( + &mut AppendGraph, + ) -> ( + [::Vertex; V], + [::Edge; E], + ), +) -> (G, [G::Vertex; V], [G::Edge; E]) +where + G: GraphTopologyConversion, +{ + let mut builder = AppendGraph::new(); + let (vertices, edges) = generator(&mut builder); + let (graph, iso) = G::convert(&builder); + ( + graph, + vertices.map(|v| iso.vertex(v)), + edges.map(|e| iso.edge(e)), + ) +} /// Generates a Petersen graph. /// @@ -43,7 +85,6 @@ where #[cfg(test)] mod tests { use super::*; - use crate::models::AppendGraph; #[test] fn petersen() {