#![recursion_limit = "256"]
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate rs_graph;
extern crate syn;
use proc_macro::TokenStream;
#[proc_macro_derive(Graph, attributes(graph))]
pub fn graph(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;
let mut var = None;
let mut typ = None;
let fields = match ast.data {
syn::Data::Struct(syn::DataStruct { ref fields, .. }) => fields.iter().enumerate().filter_map(|(i, field)| {
if &field.ident.as_ref().map(|id| id.as_ref()).unwrap_or("") == &"graph" {
var = Some("graph".into());
typ = Some(&field.ty);
None
} else if field.attrs.iter().any(|attr| {
attr.path.segments.len() == 1
&& attr.path.segments.first().unwrap().into_value().ident == syn::Ident::from("graph")
}) {
Some((
field
.ident
.clone()
.unwrap_or_else(|| syn::Ident::from(format!("{}", i))),
&field.ty,
))
} else {
None
}
}),
_ => panic!("Only structs containing a graph field can be derived."),
}.collect::<Vec<_>>();
if fields.is_empty() && var.is_none() {
panic!("No field named `graph` or with #[graph] attribute found");
} else if fields.len() > 1 {
panic!(
"Multiple fields with #[graph] attribute found: {}",
fields
.iter()
.map(|&(ref name, _)| name.as_ref())
.collect::<Vec<_>>()
.join(", ")
);
} else if !fields.is_empty() {
let field = fields.into_iter().next().unwrap();
var = Some(field.0);
typ = Some(field.1);
}
let expanded = quote! {
impl<'a> Graph<'a> for #name
where #typ: Graph<'a>
{
type Node = <#typ as Graph<'a>>::Node;
type Edge = <#typ as Graph<'a>>::Edge;
type NodeIter = <#typ as Graph<'a>>::NodeIter;
type EdgeIter = <#typ as Graph<'a>>::EdgeIter;
type NeighIter = <#typ as Graph<'a>>::NeighIter;
fn num_nodes(&self) -> usize {
self.#var.num_nodes()
}
fn num_edges(&self) -> usize {
self.#var.num_edges()
}
fn enodes(&'a self, e: Self::Edge) -> (Self::Node, Self::Node) {
self.#var.enodes(e)
}
fn nodes(&'a self) -> Self::NodeIter {
self.#var.nodes()
}
fn edges(&'a self) -> Self::EdgeIter {
self.#var.edges()
}
fn neighs(&'a self, u: Self::Node) -> Self::NeighIter {
self.#var.neighs(u)
}
}
impl<'a> ::rs_graph::Digraph<'a> for #name
where
#typ: ::rs_graph::Digraph<'a>,
{
type OutEdgeIter = <#typ as ::rs_graph::Digraph<'a>>::OutEdgeIter;
type InEdgeIter = <#typ as ::rs_graph::Digraph<'a>>::InEdgeIter;
fn src(&'a self, e: Self::Edge) -> Self::Node {
self.#var.src(e)
}
fn snk(&'a self, e: Self::Edge) -> Self::Node {
self.#var.snk(e)
}
fn outedges(&'a self, u: Self::Node) -> Self::OutEdgeIter {
self.#var.outedges(u)
}
fn inedges(&'a self, u: Self::Node) -> Self::InEdgeIter {
self.#var.inedges(u)
}
}
impl<'a> ::rs_graph::Network<'a> for #name
where
#typ: ::rs_graph::Network<'a>,
{
fn is_reverse(&self, e: Self::Edge, f: Self::Edge) -> bool {
self.#var.is_reverse(e, f)
}
fn reverse(&'a self, e: Self::Edge) -> Self::Edge {
self.#var.reverse(e)
}
fn is_forward(&self, e: Self::Edge) -> bool {
self.#var.is_forward(e)
}
fn forward(&'a self, e: Self::Edge) -> Self::Edge {
self.#var.forward(e)
}
fn is_backward(&self, e: Self::Edge) -> bool {
self.#var.is_backward(e)
}
fn backward(&'a self, e: Self::Edge) -> Self::Edge {
self.#var.backward(e)
}
fn bisrc(&'a self, e: Self::Edge) -> Self::Node {
self.#var.bisrc(e)
}
fn bisnk(&'a self, e: Self::Edge) -> Self::Node {
self.#var.bisnk(e)
}
}
impl<'a> ::rs_graph::IndexGraph<'a> for #name
where #typ: ::rs_graph::IndexGraph<'a>
{
fn node_id(&self, u: Self::Node) -> usize {
self.#var.node_id(u)
}
fn id2node(&'a self, id: usize) -> Self::Node {
self.#var.id2node(id)
}
fn edge_id(&self, e: Self::Edge) -> usize {
self.#var.edge_id(e)
}
fn id2edge(&'a self, id: usize) -> Self::Edge {
self.#var.id2edge(id)
}
}
impl<'a> ::rs_graph::IndexNetwork<'a> for #name
where
#typ: ::rs_graph::IndexNetwork<'a>,
{
fn biedge_id(&self, e: Self::Edge) -> usize {
self.#var.biedge_id(e)
}
fn id2biedge(&'a self, id: usize) -> Self::Edge {
self.#var.id2biedge(id)
}
}
};
expanded.into()
}