use crate::vgi::error::VgiResult;
use crate::vgi::metadata::{GraphMetadata, GraphType};
use crate::vgi::traits::{BackendConfig, VirtualGraph};
use std::collections::HashMap;
use std::marker::PhantomData;
pub struct GraphBuilder<N, E, G>
where
G: VirtualGraph<NodeData = N, EdgeData = E>,
{
graph_type: Option<GraphType>,
node_capacity: Option<usize>,
edge_capacity: Option<usize>,
metadata: Option<GraphMetadata>,
config: HashMap<String, String>,
_phantom: PhantomData<(N, E, G)>,
}
impl<N, E, G> GraphBuilder<N, E, G>
where
G: VirtualGraph<NodeData = N, EdgeData = E>,
{
pub fn new() -> Self {
Self {
graph_type: None,
node_capacity: None,
edge_capacity: None,
metadata: None,
config: HashMap::new(),
_phantom: PhantomData,
}
}
pub fn directed(mut self) -> Self {
self.graph_type = Some(GraphType::Directed);
self
}
pub fn undirected(mut self) -> Self {
self.graph_type = Some(GraphType::Undirected);
self
}
pub fn with_graph_type(mut self, graph_type: GraphType) -> Self {
self.graph_type = Some(graph_type);
self
}
pub fn with_capacity(mut self, nodes: usize, edges: usize) -> Self {
self.node_capacity = Some(nodes);
self.edge_capacity = Some(edges);
self
}
pub fn with_node_capacity(mut self, capacity: usize) -> Self {
self.node_capacity = Some(capacity);
self
}
pub fn with_edge_capacity(mut self, capacity: usize) -> Self {
self.edge_capacity = Some(capacity);
self
}
pub fn with_metadata(mut self, metadata: GraphMetadata) -> Self {
self.metadata = Some(metadata);
self
}
pub fn with_config(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.config.insert(key.into(), value.into());
self
}
pub fn build(self) -> G
where
G: Default,
{
G::default()
}
pub fn build_with_config(self, backend_config: BackendConfig) -> VgiResult<G>
where
G: Default,
{
let graph = G::default();
let _ = backend_config;
Ok(graph)
}
}
impl<N, E, G> Default for GraphBuilder<N, E, G>
where
G: VirtualGraph<NodeData = N, EdgeData = E>,
{
fn default() -> Self {
Self::new()
}
}
pub trait GraphBuilderTrait: VirtualGraph + Sized {
fn builder() -> GraphBuilder<Self::NodeData, Self::EdgeData, Self> {
GraphBuilder::new()
}
fn directed() -> Self;
fn undirected() -> Self;
fn with_capacity(nodes: usize, edges: usize) -> Self;
fn with_metadata(metadata: GraphMetadata) -> Self;
}
pub mod helpers {
use super::*;
pub fn directed_graph<N, E, G>() -> G
where
G: VirtualGraph<NodeData = N, EdgeData = E> + Default,
{
G::default()
}
pub fn undirected_graph<N, E, G>() -> G
where
G: VirtualGraph<NodeData = N, EdgeData = E> + Default,
{
G::default()
}
pub fn with_capacity<N, E, G>(_nodes: usize, _edges: usize) -> G
where
G: VirtualGraph<NodeData = N, EdgeData = E> + Default,
{
G::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::Graph;
use crate::graph::traits::GraphOps;
#[test]
fn test_graph_builder_basic() {
let builder: GraphBuilder<String, f64, Graph<String, f64>> = GraphBuilder::new();
let graph: Graph<String, f64> = builder.directed().build();
assert_eq!(graph.node_count(), 0);
assert_eq!(graph.edge_count(), 0);
}
#[test]
fn test_graph_builder_chain() {
let graph: Graph<i32, f64> = Graph::<i32, f64>::builder()
.undirected()
.with_capacity(100, 200)
.with_config("custom_key", "custom_value")
.build();
assert_eq!(graph.node_count(), 0);
assert_eq!(graph.edge_count(), 0);
}
#[test]
fn test_graph_builder_with_metadata() {
let _builder = GraphBuilder::<String, f64, Graph<String, f64>>::new()
.with_metadata(GraphMetadata::new("test", GraphType::Undirected));
}
#[test]
fn test_helpers() {
let _builder = GraphBuilder::<String, f64, Graph<String, f64>>::new();
}
}