1use std::cmp::Ordering;
2use std::fmt::{self, Display};
3use std::hash::{Hash, Hasher};
4
5use proc_macro2::{Ident, Span};
6
7#[cfg(feature = "parsing")]
8use crate::lookahead;
9
10#[cfg_attr(feature = "extra-traits", derive(Debug))]
24#[derive(Clone)]
25pub struct Lifetime {
26 pub apostrophe: Span,
27 pub ident: Ident,
28}
29
30impl Lifetime {
31 pub fn new(symbol: &str, span: Span) -> Self {
46 if !symbol.starts_with('\'') {
47 panic!(
48 "lifetime name must start with apostrophe as in \"'a\", got {:?}",
49 symbol
50 );
51 }
52
53 if symbol == "'" {
54 panic!("lifetime name must not be empty");
55 }
56
57 if !crate::ident::xid_ok(&symbol[1..]) {
58 panic!("{:?} is not a valid lifetime name", symbol);
59 }
60
61 Lifetime {
62 apostrophe: span,
63 ident: Ident::new(&symbol[1..], span),
64 }
65 }
66}
67
68impl Display for Lifetime {
69 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70 "'".fmt(formatter)?;
71 self.ident.fmt(formatter)
72 }
73}
74
75impl PartialEq for Lifetime {
76 fn eq(&self, other: &Lifetime) -> bool {
77 self.ident.eq(&other.ident)
78 }
79}
80
81impl Eq for Lifetime {}
82
83impl PartialOrd for Lifetime {
84 fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
85 Some(self.cmp(other))
86 }
87}
88
89impl Ord for Lifetime {
90 fn cmp(&self, other: &Lifetime) -> Ordering {
91 self.ident.cmp(&other.ident)
92 }
93}
94
95impl Hash for Lifetime {
96 fn hash<H: Hasher>(&self, h: &mut H) {
97 self.ident.hash(h)
98 }
99}
100
101#[cfg(feature = "parsing")]
102#[doc(hidden)]
103#[allow(non_snake_case)]
104pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
105 match marker {}
106}
107
108#[cfg(feature = "parsing")]
109pub mod parsing {
110 use super::*;
111
112 use crate::parse::{Parse, ParseStream, Result};
113
114 impl Parse for Lifetime {
115 fn parse(input: ParseStream) -> Result<Self> {
116 input.step(|cursor| {
117 cursor
118 .lifetime()
119 .ok_or_else(|| cursor.error("expected lifetime"))
120 })
121 }
122 }
123}
124
125#[cfg(feature = "printing")]
126mod printing {
127 use super::*;
128
129 use proc_macro2::{Punct, Spacing, TokenStream};
130 use quote::{ToTokens, TokenStreamExt};
131
132 impl ToTokens for Lifetime {
133 fn to_tokens(&self, tokens: &mut TokenStream) {
134 let mut apostrophe = Punct::new('\'', Spacing::Joint);
135 apostrophe.set_span(self.apostrophe);
136 tokens.append(apostrophe);
137 self.ident.to_tokens(tokens);
138 }
139 }
140}