]> git.proxmox.com Git - rustc.git/blame - src/vendor/syn-0.12.15/src/lifetime.rs
New upstream version 1.27.2+dfsg1
[rustc.git] / src / vendor / syn-0.12.15 / src / lifetime.rs
CommitLineData
83c7162d
XL
1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use 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/// A Rust lifetime: `'a`.
17///
18/// Lifetime names must conform to the following rules:
19///
20/// - Must start with an apostrophe.
21/// - Must not consist of just an apostrophe: `'`.
22/// - Character after the apostrophe must be `_` or a Unicode code point with
23/// the XID_Start property.
24/// - All following characters must be Unicode code points with the XID_Continue
25/// property.
26///
27/// *This type is available if Syn is built with the `"derive"` or `"full"`
28/// feature.*
29#[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}