use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};
use proc_macro2::Term;
use unicode_xid::UnicodeXID;
use Span;
#[cfg_attr(feature = "extra-traits", derive(Debug))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct Lifetime {
pub sym: Term,
pub span: Span,
}
impl Lifetime {
pub fn new(sym: Term, span: Span) -> Self {
let s = sym.as_str();
if !s.starts_with('\'') {
panic!("lifetime name must start with apostrophe as in \"'a\", \
got {:?}",
s);
}
if s == "'" {
panic!("lifetime name must not be empty");
}
if s == "'_" {
panic!("\"'_\" is not a valid lifetime name");
}
fn xid_ok(s: &str) -> bool {
let mut chars = s.chars();
let first = chars.next().unwrap();
if !(UnicodeXID::is_xid_start(first) || first == '_') {
return false;
}
for ch in chars {
if !UnicodeXID::is_xid_continue(ch) {
return false;
}
}
true
}
if !xid_ok(&s[1..]) {
panic!("{:?} is not a valid lifetime name");
}
Lifetime {
sym: sym,
span: span,
}
}
}
impl Display for Lifetime {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.sym.as_str().fmt(formatter)
}
}
impl PartialEq for Lifetime {
fn eq(&self, other: &Lifetime) -> bool {
self.sym.as_str() == other.sym.as_str()
}
}
impl Eq for Lifetime {}
impl PartialOrd for Lifetime {
fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Lifetime {
fn cmp(&self, other: &Lifetime) -> Ordering {
self.sym.as_str().cmp(other.sym.as_str())
}
}
impl Hash for Lifetime {
fn hash<H: Hasher>(&self, h: &mut H) {
self.sym.as_str().hash(h)
}
}
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use synom::{Synom, PResult, Cursor, parse_error};
impl Synom for Lifetime {
fn parse(input: Cursor) -> PResult<Self> {
let (rest, span, sym) = match input.word() {
Some(word) => word,
_ => return parse_error(),
};
if !sym.as_str().starts_with('\'') {
return parse_error();
}
Ok((rest, Lifetime {
sym: sym,
span: Span(span),
}))
}
}
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
use quote::{Tokens, ToTokens};
use proc_macro2::{TokenTree, TokenNode};
impl ToTokens for Lifetime {
fn to_tokens(&self, tokens: &mut Tokens) {
tokens.append(TokenTree {
span: self.span.0,
kind: TokenNode::Term(self.sym),
})
}
}
}