1#![recursion_limit = "256"]
19#![forbid(unsafe_code)]
20
21use quote::{format_ident, quote};
156#[allow(unused_imports)]
157use syn::Token; use syn::{self, parse_quote};
159
160use proc_macro::TokenStream;
161use proc_macro2::Span;
162use proc_macro2::TokenStream as TokenStream2;
163
164#[derive(Debug, PartialEq)]
165struct Var {
166 name: syn::Ident,
167 typ: syn::Type,
168}
169
170struct StructInfo {
171 name: syn::Ident,
172 visibility: syn::Visibility,
173 generic_parameters: syn::Generics,
174
175 graph: Var,
176
177 node_attr: Option<Var>,
178 edge_attr: Option<Var>,
179}
180
181fn parse_graph_structure(input: TokenStream2) -> StructInfo {
182 let mut ast: syn::DeriveInput = syn::parse2(input).unwrap();
183 let vis = &ast.vis;
184 let name = &ast.ident;
185 let generics = &mut ast.generics;
186
187 let mut have_graph_attr = false;
188 let mut graph = None;
189
190 let mut node_attr = None;
191 let mut edge_attr = None;
192
193 if let syn::Data::Struct(syn::DataStruct { ref fields, .. }) = ast.data {
195 for (i, ref field) in fields.iter().enumerate() {
196 if let Some(attrvar) = get_attr_var(field, i, "nodeattrs") {
197 if node_attr.is_some() {
198 panic!("Only one field can be tagged `nodeattrs`");
199 }
200 node_attr = Some(attrvar);
201 }
202
203 if let Some(attrvar) = get_attr_var(field, i, "edgeattrs") {
204 if edge_attr.is_some() {
205 panic!("Only one field can be tagged `edgeattrs`");
206 }
207 edge_attr = Some(attrvar);
208 }
209
210 if field.attrs.iter().any(|attr| attr.path.is_ident("graph")) {
211 if have_graph_attr {
212 panic!("Only one field can be tagged `graph`");
213 }
214 have_graph_attr = true;
215 } else if field.ident.as_ref().map(|s| s == "graph").unwrap_or(false) {
216 if have_graph_attr {
217 continue;
218 }
219 } else {
220 continue;
221 }
222
223 graph = Some(Var {
224 name: field.ident.clone().unwrap_or_else(|| format_ident!("{}", i)),
225 typ: field.ty.clone(),
226 });
227 }
228 }
229
230 StructInfo {
231 name: name.clone(),
232 visibility: vis.clone(),
233 generic_parameters: generics.clone(),
234
235 graph: graph.expect("No field `graph` or field with attribute #[graph] found"),
236 node_attr,
237 edge_attr,
238 }
239}
240
241fn get_attr_var(field: &syn::Field, index: usize, attrname: &str) -> Option<Var> {
242 for attr in field.attrs.iter() {
243 if attr.path.is_ident(attrname) {
244 return Some(Var {
245 name: field.ident.clone().unwrap_or_else(|| format_ident!("{}", index)),
246 typ: match attr
247 .parse_meta()
248 .unwrap_or_else(|_| panic!("Missing `{}` type", attrname))
249 {
250 syn::Meta::List(list) => {
251 assert_eq!(
252 list.nested.len(),
253 1,
254 "expected exactly one type argument for `{}`",
255 attrname
256 );
257 if let Some(syn::NestedMeta::Meta(syn::Meta::Path(id))) = list.nested.iter().next() {
258 syn::Type::Path(syn::TypePath {
261 qself: None,
262 path: id.clone(),
263 })
264 } else {
265 panic!("expected exactly one type argument for `{}`", attrname);
266 }
267 }
268 _ => panic!("expected exactly one type argument for `{}`", attrname),
269 },
270 });
271 }
272 }
273
274 None
275}
276
277fn graph_derive(input: TokenStream2) -> TokenStream2 {
278 let graph = parse_graph_structure(input);
279
280 let name = graph.name;
281 let generics = graph.generic_parameters;
282 let vis = graph.visibility;
283 let var = graph.graph.name;
284 let typ = graph.graph.typ;
285 let nodeattrs = graph.node_attr;
286 let edgeattrs = graph.edge_attr;
287
288 let ident_it = format_ident!("{}", "__rs_graph_I__");
291 let ident_lt = syn::Lifetime::new("'__rs_graph_z__", Span::call_site());
292 let ty_generics = generics.clone();
293 let mut it_generics = generics.clone();
294 it_generics
295 .params
296 .push(syn::GenericParam::Type(ident_it.clone().into()));
297 let gens = [
302 "GraphType",
303 "FiniteGraph",
304 "FiniteDigraph",
305 "Undirected",
306 "Directed",
307 "IndexGraph",
308 ]
309 .iter()
310 .map(|name| {
311 let name = format_ident!("{}", name);
312 let mut g = generics.clone();
313 g.make_where_clause()
314 .predicates
315 .push(parse_quote!(#typ: ::rs_graph::traits::#name));
316 g
318 })
319 .collect::<Vec<_>>();
320
321 let (basegraph_impl, _, basegraph_where) = gens[0].split_for_impl();
322 let (finitegraph_impl, _, finitegraph_where) = gens[1].split_for_impl();
323 let (finitedigraph_impl, _, finitedigraph_where) = gens[2].split_for_impl();
324 let (undirected_impl, _, undirected_where) = gens[3].split_for_impl();
325 let (directed_impl, _, directed_where) = gens[4].split_for_impl();
326 let (indexgraph_impl, _, indexgraph_where) = gens[5].split_for_impl();
327
328 let mut expanded = quote! {
329 impl #it_generics ::rs_graph::traits::GraphIterator<#name #ty_generics> for ::rs_graph::traits::refs::WrapIt<#ident_it> where #ident_it: GraphIterator<#typ> {
330 type Item = #ident_it :: Item;
331
332 fn next(&mut self, g: &#name #ty_generics) -> Option<Self::Item> {
333 self.0.next(&g.#var)
334 }
335 }
336
337 impl #basegraph_impl ::rs_graph::traits::GraphType for #name #ty_generics #basegraph_where
338 {
339 type Node<#ident_lt> = <#typ as ::rs_graph::traits::GraphType>::Node<#ident_lt>;
340
341 type Edge<#ident_lt> = <#typ as ::rs_graph::traits::GraphType>::Edge<#ident_lt>;
342 }
343
344 impl #finitegraph_impl ::rs_graph::traits::FiniteGraph for #name #ty_generics #finitegraph_where
345 {
346 type NodeIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::FiniteGraph>::NodeIt<#ident_lt>>;
347
348 type EdgeIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::FiniteGraph>::EdgeIt<#ident_lt>>;
349
350 fn num_nodes(&self) -> usize {
351 self.#var.num_nodes()
352 }
353
354 fn num_edges(&self) -> usize {
355 self.#var.num_edges()
356 }
357
358 fn nodes_iter(&self) -> Self::NodeIt<'_> {
359 ::rs_graph::traits::refs::WrapIt(self.#var.nodes_iter())
360 }
361
362 fn edges_iter(&self) -> Self::EdgeIt<'_> {
363 ::rs_graph::traits::refs::WrapIt(self.#var.edges_iter())
364 }
365
366 fn enodes(&self, e: Self::Edge<'_>) -> (Self::Node<'_>, Self::Node<'_>) {
367 self.#var.enodes(e)
368 }
369 }
370
371 impl #finitedigraph_impl ::rs_graph::traits::FiniteDigraph for #name #ty_generics #finitedigraph_where
372 {
373 fn src(&self, e: Self::Edge<'_>) -> Self::Node<'_> {
374 self.#var.src(e)
375 }
376
377 fn snk(&self, e: Self::Edge<'_>) -> Self::Node<'_> {
378 self.#var.snk(e)
379 }
380 }
381
382 impl #undirected_impl ::rs_graph::traits::Undirected for #name #ty_generics #undirected_where
383 {
384 type NeighIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::Undirected>::NeighIt<#ident_lt>>;
385
386 fn neigh_iter(&self, u: Self::Node<'_>) -> Self::NeighIt<'_> {
387 ::rs_graph::traits::refs::WrapIt(self.#var.neigh_iter(u))
388 }
389 }
390
391 impl #directed_impl ::rs_graph::traits::Directed for #name #ty_generics #directed_where
392 {
393 type OutIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::Directed>::OutIt<#ident_lt>>;
394
395 type InIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::Directed>::InIt<#ident_lt>>;
396
397 type IncidentIt<#ident_lt> where Self: #ident_lt = ::rs_graph::traits::refs::WrapIt<<#typ as ::rs_graph::traits::Directed>::IncidentIt<#ident_lt>>;
398
399 type DirectedEdge<#ident_lt> where Self: #ident_lt = <#typ as ::rs_graph::traits::Directed>::DirectedEdge<#ident_lt>;
400
401 fn out_iter(&self, u: Self::Node<'_>) -> Self::OutIt<'_> {
402 ::rs_graph::traits::refs::WrapIt(self.#var.out_iter(u))
403 }
404
405 fn in_iter(&self, u: Self::Node<'_>) -> Self::InIt<'_> {
406 ::rs_graph::traits::refs::WrapIt(self.#var.in_iter(u))
407 }
408
409 fn incident_iter(&self, u: Self::Node<'_>) -> Self::IncidentIt<'_> {
410 ::rs_graph::traits::refs::WrapIt(self.#var.incident_iter(u))
411 }
412 }
413
414 impl #indexgraph_impl ::rs_graph::traits::IndexGraph for #name #ty_generics #indexgraph_where
415 {
416 fn node_id(&self, u: Self::Node<'_>) -> usize {
417 self.#var.node_id(u)
418 }
419
420 fn id2node(&self, id: usize) -> Self::Node<'_> {
421 self.#var.id2node(id)
422 }
423
424 fn edge_id(&self, e: Self::Edge<'_>) -> usize {
425 self.#var.edge_id(e)
426 }
427
428 fn id2edge(&self, id: usize) -> Self::Edge<'_> {
429 self.#var.id2edge(id)
430 }
431 }
432 };
433
434 let mut attrdefs = TokenStream2::new();
435 let mut attrsets = TokenStream2::new();
436 let mut attrsets2 = TokenStream2::new();
437 if let Some(Var {
438 name: attrvar,
439 typ: attrtyp,
440 }) = nodeattrs.as_ref()
441 {
442 expanded.extend(quote! {
443 impl #indexgraph_impl ::rs_graph::attributes::NodeAttributes<#typ, #attrtyp> for #name #ty_generics #indexgraph_where
444 {
445 fn node(&self, u: <#typ as ::rs_graph::traits::GraphType>::Node<'_>) -> &#attrtyp {
446 &self.#attrvar[self.#var.node_id(u)]
447 }
448
449 fn node_mut(&mut self, u: <#typ as ::rs_graph::traits::GraphType>::Node<'_>) -> &mut #attrtyp {
450 &mut self.#attrvar[self.#var.node_id(u)]
451 }
452 }
453 });
454 attrdefs.extend(quote!(nodeattrs: &#ident_lt mut [#attrtyp],));
455 attrsets.extend(quote!(nodeattrs: &mut self.#attrvar,));
456 attrsets2.extend(quote!(nodeattrs: self.nodeattrs,));
457 }
458
459 if let Some(Var {
460 name: attrvar,
461 typ: attrtyp,
462 }) = edgeattrs.as_ref()
463 {
464 expanded.extend(quote! {
465 impl #indexgraph_impl ::rs_graph::attributes::EdgeAttributes<#typ, #attrtyp> for #name #ty_generics #indexgraph_where
466 {
467 fn edge(&self, u: <#typ as ::rs_graph::traits::GraphType>::Edge<'_>) -> &#attrtyp {
468 &self.#attrvar[self.#var.edge_id(u)]
469 }
470
471 fn edge_mut(&mut self, u: <#typ as ::rs_graph::traits::GraphType>::Edge<'_>) -> &mut #attrtyp {
472 &mut self.#attrvar[self.#var.edge_id(u)]
473 }
474 }
475 });
476 attrdefs.extend(quote!(edgeattrs: &#ident_lt mut [#attrtyp],));
477 attrsets.extend(quote!(edgeattrs: &mut self.#attrvar,));
478 attrsets2.extend(quote!(edgeattrs: self.edgeattrs,));
479 }
480
481 if !attrdefs.is_empty() {
482 let (_, orig_ty_generics, orig_where) = ty_generics.split_for_impl();
483 let attrstruct = format_ident!("{}_Attributes", name);
484 expanded.extend(quote! {
485 #vis struct #attrstruct<#ident_lt> {
486 graph: &#ident_lt #typ,
487 #attrdefs
488 }
489
490 impl #basegraph_impl ::rs_graph::attributes::AttributedGraph for #name #orig_ty_generics #orig_where {
491 type Graph = #typ;
492 type Attributes<#ident_lt> = #attrstruct<#ident_lt>;
493 fn split(&mut self) -> (&#typ, #attrstruct<'_>) {
494 (
495 &self.#var,
496 #attrstruct {
497 graph: &self.#var,
498 #attrsets
499 },
500 )
501 }
502 }
503
504 });
515
516 if let Some(Var { typ: attrtyp, .. }) = nodeattrs.as_ref() {
517 expanded.extend(quote! {
518 impl<#ident_lt> #indexgraph_impl ::rs_graph::attributes::NodeAttributes<#typ, #attrtyp> for #attrstruct <#ident_lt> #indexgraph_where
519 {
520 fn node(&self, u: <#typ as ::rs_graph::traits::GraphType>::Node<'_>) -> &#attrtyp {
521 &self.nodeattrs[self.#var.node_id(u)]
522 }
523
524 fn node_mut(&mut self, u: <#typ as ::rs_graph::traits::GraphType>::Node<'_>) -> &mut #attrtyp {
525 &mut self.nodeattrs[self.#var.node_id(u)]
526 }
527 }
528 });
529 }
530
531 if let Some(Var { typ: attrtyp, .. }) = edgeattrs.as_ref() {
532 expanded.extend(quote! {
533 impl<#ident_lt> #indexgraph_impl ::rs_graph::attributes::EdgeAttributes<#typ, #attrtyp> for #attrstruct <#ident_lt> #indexgraph_where
534 {
535 fn edge(&self, u: <#typ as ::rs_graph::traits::GraphType>::Edge<'_>) -> &#attrtyp {
536 &self.edgeattrs[self.#var.edge_id(u)]
537 }
538
539 fn edge_mut(&mut self, u: <#typ as ::rs_graph::traits::GraphType>::Edge<'_>) -> &mut #attrtyp {
540 &mut self.edgeattrs[self.#var.edge_id(u)]
541 }
542 }
543 });
544 }
545 }
546
547 expanded
548}
549
550#[proc_macro_derive(Graph, attributes(graph, nodeattrs, edgeattrs))]
551pub fn graph(input: TokenStream) -> TokenStream {
552 graph_derive(TokenStream2::from(input)).into()
553}
554
555#[cfg(test)]
556mod tests {
557 use super::*;
558
559 fn var(name: &str, vartyp: &str) -> Var {
560 Var {
561 name: format_ident!("{}", name),
562 typ: typ(vartyp),
563 }
564 }
565
566 fn typ(t: &str) -> syn::Type {
567 syn::TypePath {
568 qself: None,
569 path: format_ident!("{}", t).into(),
570 }
571 .into()
572 }
573
574 #[test]
575 fn test_parse_simple_graph() {
576 let g = parse_graph_structure(quote!(
577 struct MyGraph {
578 graph: Graph,
579 other: usize,
580 }
581 ));
582 assert_eq!(g.name, "MyGraph");
583 assert_eq!(g.visibility, syn::Visibility::Inherited);
584 assert!(g.generic_parameters.params.is_empty());
585 assert!(g.generic_parameters.where_clause.is_none());
586 assert_eq!(g.graph, var("graph", "Graph"));
587 assert!(g.node_attr.is_none());
588 assert!(g.edge_attr.is_none());
589 }
590
591 #[test]
592 fn test_parse_simple_graph_with_graph_tag() {
593 let g = parse_graph_structure(quote!(
594 struct MyGraph {
595 graph: usize,
596 #[graph]
597 other: Graph,
598 }
599 ));
600 assert_eq!(g.name, "MyGraph");
601 assert_eq!(g.visibility, syn::Visibility::Inherited);
602 assert!(g.generic_parameters.params.is_empty());
603 assert!(g.generic_parameters.where_clause.is_none());
604 assert_eq!(g.graph, var("other", "Graph"));
605 assert!(g.node_attr.is_none());
606 assert!(g.edge_attr.is_none());
607 }
608
609 #[test]
610 #[should_panic]
611 fn test_parse_simple_graph_without_graph_tag() {
612 parse_graph_structure(quote!(
613 struct MyGraph {
614 something: usize,
615 other: Graph,
616 }
617 ));
618 }
619
620 #[test]
621 #[should_panic]
622 fn test_parse_simple_graph_with_multiple_graph_tags() {
623 parse_graph_structure(quote!(
624 struct MyGraph {
625 #[graph]
626 something: Graph,
627 #[graph]
628 other: Graph,
629 }
630 ));
631 }
632
633 #[test]
634 fn test_parse_graph_with_node_attr() {
635 let g = parse_graph_structure(quote!(
636 struct MyGraph {
637 graph: Graph,
638 #[nodeattrs(NodeData)]
639 nodes: Vec<NodeData>,
640 }
641 ));
642 assert_eq!(g.name, "MyGraph");
643 assert_eq!(g.visibility, syn::Visibility::Inherited);
644 assert!(g.generic_parameters.params.is_empty());
645 assert!(g.generic_parameters.where_clause.is_none());
646 assert_eq!(g.graph, var("graph", "Graph"));
647 assert_eq!(g.node_attr, Some(var("nodes", "NodeData")));
648 assert!(g.edge_attr.is_none());
649 }
650
651 #[test]
652 #[should_panic]
653 fn test_parse_graph_with_multiple_node_attr() {
654 parse_graph_structure(quote!(
655 struct MyGraph {
656 graph: Graph,
657 #[nodeattrs(NodeData)]
658 nodes: Vec<NodeData>,
659 #[nodeattrs(NodeData)]
660 nodes2: Vec<NodeData>,
661 }
662 ));
663 }
664
665 #[test]
666 fn test_parse_graph_with_edge_attr() {
667 let g = parse_graph_structure(quote!(
668 struct MyGraph {
669 graph: Graph,
670 #[edgeattrs(EdgeData)]
671 edges: Vec<EdgeData>,
672 }
673 ));
674 assert_eq!(g.name, "MyGraph");
675 assert_eq!(g.visibility, syn::Visibility::Inherited);
676 assert!(g.generic_parameters.params.is_empty());
677 assert!(g.generic_parameters.where_clause.is_none());
678 assert_eq!(g.graph, var("graph", "Graph"));
679 assert!(g.node_attr.is_none());
680 assert_eq!(g.edge_attr, Some(var("edges", "EdgeData")));
681 }
682
683 #[test]
684 #[should_panic]
685 fn test_parse_graph_with_multiple_edge_attr() {
686 parse_graph_structure(quote!(
687 struct MyGraph {
688 graph: Graph,
689 #[edgeattrs(EdgeData)]
690 edges: Vec<EdgeData>,
691 #[edgeattrs(EdgeData)]
692 edges2: Vec<EdgeData>,
693 }
694 ));
695 }
696
697 #[test]
698 fn test_parse_graph_with_visiblity() {
699 let g = parse_graph_structure(quote!(
700 pub struct MyGraph {
701 graph: Graph,
702 other: usize,
703 }
704 ));
705 assert_eq!(g.name, "MyGraph");
706 assert_eq!(
707 g.visibility,
708 syn::VisPublic {
709 pub_token: <Token![pub]>::default().into()
710 }
711 .into()
712 );
713 assert!(g.generic_parameters.params.is_empty());
714 assert!(g.generic_parameters.where_clause.is_none());
715 assert_eq!(g.graph, var("graph", "Graph"));
716 assert!(g.node_attr.is_none());
717 assert!(g.edge_attr.is_none());
718 }
719
720 #[test]
721 fn test_graph_traits() {
722 let generated = graph_derive(quote!(
723 struct MyGraph {
724 graph: Graph,
725 }
726 ));
727
728 let expected = quote! {
729 impl<__rs_graph_I__>::rs_graph::traits::GraphIterator<MyGraph>
730 for ::rs_graph::traits::refs::WrapIt<__rs_graph_I__>
731 where
732 __rs_graph_I__: GraphIterator<Graph>
733 {
734 type Item = __rs_graph_I__::Item;
735 fn next(&mut self, g: &MyGraph) -> Option<Self::Item> {
736 self.0.next(&g.graph)
737 }
738 }
739 };
740
741 assert!(generated.to_string().starts_with(&expected.to_string()));
742 }
743}