use std::{convert::TryFrom, marker::PhantomData};
use crate::{
graph::csr::{CsrLayout, NodeValues},
index::Idx,
input::{edgelist::EdgeList, InputCapabilities, InputPath},
prelude::edgelist::{EdgeIterator, EdgeWithValueIterator},
Error,
};
use std::path::Path as StdPath;
pub struct Uninitialized {
csr_layout: CsrLayout,
}
pub struct FromEdges<NI, Edges>
where
NI: Idx,
Edges: IntoIterator<Item = (NI, NI)>,
{
csr_layout: CsrLayout,
edges: Edges,
_node: PhantomData<NI>,
}
pub struct FromEdgeListAndNodeValues<NI, NV, EV>
where
NI: Idx,
{
csr_layout: CsrLayout,
node_values: NodeValues<NV>,
edge_list: EdgeList<NI, EV>,
}
pub struct FromEdgesWithValues<NI, Edges, EV>
where
NI: Idx,
Edges: IntoIterator<Item = (NI, NI, EV)>,
{
csr_layout: CsrLayout,
edges: Edges,
_node: PhantomData<NI>,
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
pub struct FromGdlString<NI>
where
NI: Idx,
{
csr_layout: CsrLayout,
gdl: String,
_node: PhantomData<NI>,
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
pub struct FromGdlGraph<'a, NI>
where
NI: Idx,
{
csr_layout: CsrLayout,
gdl_graph: &'a gdl::Graph,
_node: PhantomData<NI>,
}
pub struct FromInput<NI, P, Format>
where
P: AsRef<StdPath>,
NI: Idx,
Format: InputCapabilities<NI>,
Format::GraphInput: TryFrom<InputPath<P>>,
{
csr_layout: CsrLayout,
_idx: PhantomData<NI>,
_path: PhantomData<P>,
_format: PhantomData<Format>,
}
pub struct FromPath<NI, P, Format>
where
P: AsRef<StdPath>,
NI: Idx,
Format: InputCapabilities<NI>,
Format::GraphInput: TryFrom<InputPath<P>>,
{
csr_layout: CsrLayout,
path: P,
_idx: PhantomData<NI>,
_format: PhantomData<Format>,
}
pub struct GraphBuilder<State> {
state: State,
}
impl Default for GraphBuilder<Uninitialized> {
fn default() -> Self {
GraphBuilder::new()
}
}
impl GraphBuilder<Uninitialized> {
pub fn new() -> Self {
Self {
state: Uninitialized {
csr_layout: CsrLayout::default(),
},
}
}
#[must_use]
pub fn csr_layout(mut self, csr_layout: CsrLayout) -> Self {
self.state.csr_layout = csr_layout;
self
}
pub fn edges<NI, Edges>(self, edges: Edges) -> GraphBuilder<FromEdges<NI, Edges>>
where
NI: Idx,
Edges: IntoIterator<Item = (NI, NI)>,
{
GraphBuilder {
state: FromEdges {
csr_layout: self.state.csr_layout,
edges,
_node: PhantomData,
},
}
}
pub fn edges_with_values<NI, Edges, EV>(
self,
edges: Edges,
) -> GraphBuilder<FromEdgesWithValues<NI, Edges, EV>>
where
NI: Idx,
Edges: IntoIterator<Item = (NI, NI, EV)>,
{
GraphBuilder {
state: FromEdgesWithValues {
csr_layout: self.state.csr_layout,
edges,
_node: PhantomData,
},
}
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
pub fn gdl_str<NI, S>(self, gdl: S) -> GraphBuilder<FromGdlString<NI>>
where
NI: Idx,
S: Into<String>,
{
GraphBuilder {
state: FromGdlString {
csr_layout: self.state.csr_layout,
gdl: gdl.into(),
_node: PhantomData,
},
}
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
pub fn gdl_graph<NI>(self, gdl_graph: &::gdl::Graph) -> GraphBuilder<FromGdlGraph<NI>>
where
NI: Idx,
{
GraphBuilder {
state: FromGdlGraph {
csr_layout: self.state.csr_layout,
gdl_graph,
_node: PhantomData,
},
}
}
pub fn file_format<Format, Path, NI>(
self,
_format: Format,
) -> GraphBuilder<FromInput<NI, Path, Format>>
where
Path: AsRef<StdPath>,
NI: Idx,
Format: InputCapabilities<NI>,
Format::GraphInput: TryFrom<InputPath<Path>>,
{
GraphBuilder {
state: FromInput {
csr_layout: self.state.csr_layout,
_idx: PhantomData,
_path: PhantomData,
_format: PhantomData,
},
}
}
}
impl<NI, Edges> GraphBuilder<FromEdges<NI, Edges>>
where
NI: Idx,
Edges: IntoIterator<Item = (NI, NI)>,
{
pub fn node_values<NV, I>(
self,
node_values: I,
) -> GraphBuilder<FromEdgeListAndNodeValues<NI, NV, ()>>
where
I: IntoIterator<Item = NV>,
{
let edge_list = EdgeList::from(EdgeIterator(self.state.edges));
let node_values = node_values.into_iter().collect::<NodeValues<NV>>();
GraphBuilder {
state: FromEdgeListAndNodeValues {
csr_layout: self.state.csr_layout,
node_values,
edge_list,
},
}
}
pub fn build<Graph>(self) -> Graph
where
Graph: From<(EdgeList<NI, ()>, CsrLayout)>,
{
Graph::from((
EdgeList::from(EdgeIterator(self.state.edges)),
self.state.csr_layout,
))
}
}
impl<NI, Edges, EV> GraphBuilder<FromEdgesWithValues<NI, Edges, EV>>
where
NI: Idx,
EV: Sync,
Edges: IntoIterator<Item = (NI, NI, EV)>,
{
pub fn node_values<NV, I>(
self,
node_values: I,
) -> GraphBuilder<FromEdgeListAndNodeValues<NI, NV, EV>>
where
I: IntoIterator<Item = NV>,
{
let edge_list = EdgeList::from(EdgeWithValueIterator(self.state.edges));
let node_values = node_values.into_iter().collect::<NodeValues<NV>>();
GraphBuilder {
state: FromEdgeListAndNodeValues {
csr_layout: self.state.csr_layout,
node_values,
edge_list,
},
}
}
pub fn build<Graph>(self) -> Graph
where
Graph: From<(EdgeList<NI, EV>, CsrLayout)>,
{
Graph::from((
EdgeList::new(self.state.edges.into_iter().collect()),
self.state.csr_layout,
))
}
}
impl<NI: Idx, NV, EV> GraphBuilder<FromEdgeListAndNodeValues<NI, NV, EV>> {
pub fn build<Graph>(self) -> Graph
where
Graph: From<(NodeValues<NV>, EdgeList<NI, EV>, CsrLayout)>,
{
Graph::from((
self.state.node_values,
self.state.edge_list,
self.state.csr_layout,
))
}
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
impl<NI> GraphBuilder<FromGdlString<NI>>
where
NI: Idx,
{
pub fn build<Graph>(self) -> Result<Graph, Error>
where
Graph: From<(gdl::Graph, CsrLayout)>,
{
let gdl_graph = self.state.gdl.parse::<gdl::Graph>()?;
let graph = Graph::from((gdl_graph, self.state.csr_layout));
Ok(graph)
}
}
#[cfg(feature = "gdl")]
#[cfg_attr(all(feature = "gdl", has_doc_cfg), doc(cfg(feature = "gdl")))]
impl<'a, NI> GraphBuilder<FromGdlGraph<'a, NI>>
where
NI: Idx,
{
pub fn build<Graph>(self) -> Result<Graph, Error>
where
Graph: From<(&'a gdl::Graph, CsrLayout)>,
{
Ok(Graph::from((self.state.gdl_graph, self.state.csr_layout)))
}
}
impl<NI, Path, Format> GraphBuilder<FromInput<NI, Path, Format>>
where
Path: AsRef<StdPath>,
NI: Idx,
Format: InputCapabilities<NI>,
Format::GraphInput: TryFrom<InputPath<Path>>,
{
pub fn path(self, path: Path) -> GraphBuilder<FromPath<NI, Path, Format>> {
GraphBuilder {
state: FromPath {
csr_layout: self.state.csr_layout,
path,
_idx: PhantomData,
_format: PhantomData,
},
}
}
}
impl<NI, Path, Format> GraphBuilder<FromPath<NI, Path, Format>>
where
Path: AsRef<StdPath>,
NI: Idx,
Format: InputCapabilities<NI>,
Format::GraphInput: TryFrom<InputPath<Path>>,
crate::Error: From<<Format::GraphInput as TryFrom<InputPath<Path>>>::Error>,
{
pub fn build<Graph>(self) -> Result<Graph, Error>
where
Graph: TryFrom<(Format::GraphInput, CsrLayout)>,
crate::Error: From<Graph::Error>,
{
let input = Format::GraphInput::try_from(InputPath(self.state.path))?;
let graph = Graph::try_from((input, self.state.csr_layout))?;
Ok(graph)
}
}