1use std::cmp::{Ord, Ordering};
2use std::fmt::{self, Debug, Display};
3
4use proc_macro2::{Span, TokenStream};
5use syn::{spanned::Spanned, Ident};
6
7use crate::graph::{Disambiguate, Node};
8use crate::util::MaybeVoid;
9
10#[derive(Clone)]
11pub struct Leaf<'t> {
12 pub ident: Option<&'t Ident>,
13 pub span: Span,
14 pub priority: usize,
15 pub field: MaybeVoid,
16 pub callback: Option<Callback>,
17}
18
19#[derive(Clone)]
20pub enum Callback {
21 Label(TokenStream),
22 Inline(Box<InlineCallback>),
23 Skip(Span),
24}
25
26#[derive(Clone)]
27pub struct InlineCallback {
28 pub arg: Ident,
29 pub body: TokenStream,
30 pub span: Span,
31}
32
33impl From<InlineCallback> for Callback {
34 fn from(inline: InlineCallback) -> Callback {
35 Callback::Inline(Box::new(inline))
36 }
37}
38
39impl Callback {
40 pub fn span(&self) -> Span {
41 match self {
42 Callback::Label(tokens) => tokens.span(),
43 Callback::Inline(inline) => inline.span,
44 Callback::Skip(span) => *span,
45 }
46 }
47}
48
49impl<'t> Leaf<'t> {
50 pub fn new(ident: &'t Ident, span: Span) -> Self {
51 Leaf {
52 ident: Some(ident),
53 span,
54 priority: 0,
55 field: MaybeVoid::Void,
56 callback: None,
57 }
58 }
59
60 pub fn new_skip(span: Span) -> Self {
61 Leaf {
62 ident: None,
63 span,
64 priority: 0,
65 field: MaybeVoid::Void,
66 callback: Some(Callback::Skip(span)),
67 }
68 }
69
70 pub fn callback(mut self, callback: Option<Callback>) -> Self {
71 self.callback = callback;
72 self
73 }
74
75 pub fn field(mut self, field: MaybeVoid) -> Self {
76 self.field = field;
77 self
78 }
79
80 pub fn priority(mut self, priority: usize) -> Self {
81 self.priority = priority;
82 self
83 }
84}
85
86impl Disambiguate for Leaf<'_> {
87 fn cmp(left: &Leaf, right: &Leaf) -> Ordering {
88 Ord::cmp(&left.priority, &right.priority)
89 }
90}
91
92impl<'t> From<Leaf<'t>> for Node<Leaf<'t>> {
93 fn from(leaf: Leaf<'t>) -> Self {
94 Node::Leaf(leaf)
95 }
96}
97
98impl Debug for Leaf<'_> {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 write!(f, "::{}", self)?;
101
102 match self.callback {
103 Some(Callback::Label(ref label)) => write!(f, " ({})", label),
104 Some(Callback::Inline(_)) => f.write_str(" (<inline>)"),
105 Some(Callback::Skip(_)) => f.write_str(" (<skip>)"),
106 None => Ok(()),
107 }
108 }
109}
110
111impl Display for Leaf<'_> {
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 match self.ident {
114 Some(ident) => Display::fmt(ident, f),
115 None => f.write_str("<skip>"),
116 }
117 }
118}