standalone_syn/
lifetime.rs1use std::cmp::Ordering;
10use std::fmt::{self, Display};
11use std::hash::{Hash, Hasher};
12
13use proc_macro2::{Span, Term};
14use unicode_xid::UnicodeXID;
15
16#[cfg_attr(feature = "extra-traits", derive(Debug))]
30#[derive(Copy, Clone)]
31pub struct Lifetime {
32 term: Term,
33 pub span: Span,
34}
35
36impl Lifetime {
37 pub fn new(term: Term, span: Span) -> Self {
38 let s = term.as_str();
39
40 if !s.starts_with('\'') {
41 panic!(
42 "lifetime name must start with apostrophe as in \"'a\", \
43 got {:?}",
44 s
45 );
46 }
47
48 if s == "'" {
49 panic!("lifetime name must not be empty");
50 }
51
52 fn xid_ok(s: &str) -> bool {
53 let mut chars = s.chars();
54 let first = chars.next().unwrap();
55 if !(UnicodeXID::is_xid_start(first) || first == '_') {
56 return false;
57 }
58 for ch in chars {
59 if !UnicodeXID::is_xid_continue(ch) {
60 return false;
61 }
62 }
63 true
64 }
65
66 if !xid_ok(&s[1..]) {
67 panic!("{:?} is not a valid lifetime name", s);
68 }
69
70 Lifetime {
71 term: term,
72 span: span,
73 }
74 }
75}
76
77impl Display for Lifetime {
78 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79 self.term.as_str().fmt(formatter)
80 }
81}
82
83impl PartialEq for Lifetime {
84 fn eq(&self, other: &Lifetime) -> bool {
85 self.term.as_str() == other.term.as_str()
86 }
87}
88
89impl Eq for Lifetime {}
90
91impl PartialOrd for Lifetime {
92 fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
93 Some(self.cmp(other))
94 }
95}
96
97impl Ord for Lifetime {
98 fn cmp(&self, other: &Lifetime) -> Ordering {
99 self.term.as_str().cmp(other.term.as_str())
100 }
101}
102
103impl Hash for Lifetime {
104 fn hash<H: Hasher>(&self, h: &mut H) {
105 self.term.as_str().hash(h)
106 }
107}
108
109#[cfg(feature = "parsing")]
110pub mod parsing {
111 use super::*;
112 use synom::Synom;
113 use buffer::Cursor;
114 use parse_error;
115 use synom::PResult;
116
117 impl Synom for Lifetime {
118 fn parse(input: Cursor) -> PResult<Self> {
119 let (span, term, rest) = match input.term() {
120 Some(term) => term,
121 _ => return parse_error(),
122 };
123 if !term.as_str().starts_with('\'') {
124 return parse_error();
125 }
126
127 Ok((
128 Lifetime {
129 term: term,
130 span: span,
131 },
132 rest,
133 ))
134 }
135
136 fn description() -> Option<&'static str> {
137 Some("lifetime")
138 }
139 }
140}
141
142#[cfg(feature = "printing")]
143mod printing {
144 use super::*;
145 use quote::{ToTokens, Tokens};
146 use proc_macro2::{TokenNode, TokenTree};
147
148 impl ToTokens for Lifetime {
149 fn to_tokens(&self, tokens: &mut Tokens) {
150 tokens.append(TokenTree {
151 span: self.span,
152 kind: TokenNode::Term(self.term),
153 })
154 }
155 }
156}