use crate::{
Error, Ident, LiteralCharacter, LiteralInteger, Parse, Parser, RefineErr, Result, Span,
ToTokens, TokenIter, TokenStream, TokenTree,
};
macro_rules! impl_unsigned_integer {
($($ty:ty),*) => {
$(
#[doc = stringify!(Parse $ty may have a positive sign but no suffix)]
impl Parser for $ty {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
let lit = crate::Cons::<Option<crate::Plus>, LiteralInteger>::parser(tokens).refine_err::<Self>()?;
<$ty>::try_from(lit.second.value())
.or_else(|e| Error::dynamic::<Self>(at, tokens, e))
}
}
#[doc = stringify!(Emit a literal $ty without sign and suffix)]
impl ToTokens for $ty {
fn to_tokens(&self, tokens: &mut TokenStream) {
#[allow(clippy::cast_lossless)]
LiteralInteger::new(*self as u128).to_tokens(tokens);
}
}
#[doc = stringify!(Emit a literal $ty without sign and suffix)]
impl ToTokens for &$ty {
fn to_tokens(&self, tokens: &mut TokenStream) {
#[allow(clippy::cast_lossless)]
LiteralInteger::new(**self as u128).to_tokens(tokens);
}
}
)*
};
}
impl_unsigned_integer! {u8, u16, u32, u64, u128, usize}
macro_rules! impl_signed_integer {
($($ty:ty),*) => {
$(
#[doc = stringify!(Parse $ty may have a positive or negative sign but no suffix)]
impl Parser for $ty {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
let lit = crate::Cons::<Option<crate::Either<crate::Plus, crate::Minus>>, LiteralInteger>::parser(tokens).refine_err::<Self>()?;
let value = <$ty>::try_from(lit.second.value())
.or_else(|e| Error::dynamic::<Self>(at, tokens, e))?;
match lit.first {
Some(crate::Either::Second(_)) => Ok(-value),
_ => Ok(value),
}
}
}
#[doc = stringify!(Emit a literal $ty with negative sign and without suffix)]
impl ToTokens for $ty {
fn to_tokens(&self, tokens: &mut TokenStream) {
if *self < 0 {
crate::Minus::new().to_tokens(tokens);
}
LiteralInteger::new(self.abs().try_into().unwrap()).to_tokens(tokens);
}
}
#[doc = stringify!(Emit a literal $ty with negative sign and without suffix)]
impl ToTokens for &$ty {
fn to_tokens(&self, tokens: &mut TokenStream) {
if **self < 0 {
crate::Minus::new().to_tokens(tokens);
}
LiteralInteger::new(self.abs().try_into().unwrap()).to_tokens(tokens);
}
}
)*
};
}
impl_signed_integer! {i8, i16, i32, i64, i128, isize}
impl Parser for char {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let lit = LiteralCharacter::parser(tokens).refine_err::<Self>()?;
Ok(lit.value())
}
}
impl ToTokens for char {
fn to_tokens(&self, tokens: &mut TokenStream) {
LiteralCharacter::new(*self).to_tokens(tokens);
}
}
#[cfg(not(feature = "proc_macro2"))]
#[mutants::skip]
fn parse_bool_ident(ident: &Ident, at: Option<TokenTree>, tokens: &mut TokenIter) -> Result<bool> {
let ident_str = ident.to_string();
if ident_str == "true" {
Ok(true)
} else if ident_str == "false" {
Ok(false)
} else {
Error::unexpected_token(at, tokens)
}
}
impl Parser for bool {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
Ident::parse_with(tokens, |ident, tokens| {
#[cfg(feature = "proc_macro2")]
{
if ident == "true" {
Ok(true)
} else if ident == "false" {
Ok(false)
} else {
Error::unexpected_token(at, tokens)
}
}
#[cfg(not(feature = "proc_macro2"))]
{
parse_bool_ident(&ident, at, tokens)
}
})
.refine_err::<Self>()
}
}
impl ToTokens for bool {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(if *self { "true" } else { "false" }, Span::call_site()).to_tokens(tokens);
}
}
impl Parser for String {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
TokenTree::parse_with(tokens, |token, _| Ok(token.to_string())).refine_err::<Self>()
}
}
#[cfg(feature = "proc_macro2")]
impl ToTokens for &str {
fn to_tokens(&self, tokens: &mut TokenStream) {
use std::str::FromStr;
let ts = TokenStream::from_str(self).expect("Failed to tokenize input string.");
tokens.extend(ts);
}
}
#[cfg(feature = "proc_macro2")]
impl ToTokens for str {
fn to_tokens(&self, tokens: &mut TokenStream) {
use std::str::FromStr;
let ts = TokenStream::from_str(self).expect("Failed to tokenize input string.");
tokens.extend(ts);
}
}
#[cfg(feature = "proc_macro2")]
impl ToTokens for &String {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.as_str().to_tokens(tokens);
}
}
impl<T> Parser for std::marker::PhantomData<T> {
#[inline]
#[mutants::skip]
fn parser(_tokens: &mut TokenIter) -> Result<Self> {
Ok(Self)
}
}
impl<T> ToTokens for std::marker::PhantomData<T> {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
impl<A: Parse, B: Parse> Parser for (A, B) {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Ok((A::parser(tokens)?, B::parser(tokens)?))
}
}
impl<A: ToTokens, B: ToTokens> ToTokens for (A, B) {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
self.1.to_tokens(tokens);
}
}
impl<A: Parse, B: Parse, C: Parse> Parser for (A, B, C) {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Ok((A::parser(tokens)?, B::parser(tokens)?, C::parser(tokens)?))
}
}
impl<A: ToTokens, B: ToTokens, C: ToTokens> ToTokens for (A, B, C) {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
self.1.to_tokens(tokens);
self.2.to_tokens(tokens);
}
}
impl<A: Parse, B: Parse, C: Parse, D: Parse> Parser for (A, B, C, D) {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Ok((
A::parser(tokens)?,
B::parser(tokens)?,
C::parser(tokens)?,
D::parser(tokens)?,
))
}
}
impl<A: ToTokens, B: ToTokens, C: ToTokens, D: ToTokens> ToTokens for (A, B, C, D) {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
self.1.to_tokens(tokens);
self.2.to_tokens(tokens);
self.3.to_tokens(tokens);
}
}