use std::ffi::CStr;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
mod sealed {
pub trait Sealed {}
}
#[macro_export]
macro_rules! stream {
($($tt:tt)*) => {
stringify!($($tt)*)
.parse::<::proc_macro2::TokenStream>()
.expect("couldn't parse tokens")
};
}
#[macro_export]
macro_rules! tree {
($tt:tt) => {
$crate::stream!($tt)
.into_iter()
.next()
.expect("expected a token")
};
}
#[macro_export]
macro_rules! group {
($tt:tt) => {
$crate::TokenTreeExt::into_group($crate::tree!($tt)).expect("expected a group")
};
}
#[macro_export]
macro_rules! ident {
($tt:tt) => {
$crate::TokenTreeExt::into_ident($crate::tree!($tt)).expect("expected an ident")
};
}
#[macro_export]
macro_rules! punct {
($tt:tt) => {
$crate::TokenTreeExt::into_punct($crate::tree!($tt)).expect("expected a punct")
};
}
#[macro_export]
macro_rules! literal {
($tt:tt) => {
$crate::TokenTreeExt::into_literal($crate::tree!($tt)).expect("expected a literal")
};
}
#[macro_export]
macro_rules! assert_stream_eq {
($left:expr, $right:expr) => {
assert!($crate::TokenStreamExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_stream_ne {
($left:expr, $right:expr) => {
assert!(!$crate::TokenStreamExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_tree_eq {
($left:expr, $right:expr) => {
assert!($crate::TokenTreeExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_tree_ne {
($left:expr, $right:expr) => {
assert!(!$crate::TokenTreeExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_group_eq {
($left:expr, $right:expr) => {
assert!($crate::GroupExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_group_ne {
($left:expr, $right:expr) => {
assert!(!$crate::GroupExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_ident_eq {
($left:expr, $right:expr) => {
assert!($crate::IdentExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_ident_ne {
($left:expr, $right:expr) => {
assert!(!$crate::IdentExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_punct_eq {
($left:expr, $right:expr) => {
assert!($crate::PunctExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_punct_ne {
($left:expr, $right:expr) => {
assert!(!$crate::PunctExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_literal_eq {
($left:expr, $right:expr) => {
assert!($crate::LiteralExt::equals(&$left, &$right));
};
}
#[macro_export]
macro_rules! assert_literal_ne {
($left:expr, $right:expr) => {
assert!(!$crate::LiteralExt::equals(&$left, &$right));
};
}
pub trait TokenStreamExt: Sized + sealed::Sealed {
fn token(token: impl Into<TokenTree>) -> Self;
fn equals(&self, other: &Self) -> bool;
fn append<T>(&mut self, token: T)
where
T: Into<TokenTree>;
}
impl TokenStreamExt for TokenStream {
fn token(token: impl Into<TokenTree>) -> Self {
Self::from(token.into())
}
fn equals(&self, other: &Self) -> bool {
let mut this = self.clone().into_iter();
let mut other = other.clone().into_iter();
loop {
match (this.next(), other.next()) {
(Some(this), Some(other)) if this.equals(&other) => {}
(None, None) => return true,
_ => return false,
}
}
}
fn append<T>(&mut self, token: T)
where
T: Into<TokenTree>,
{
self.extend(Some(token.into()));
}
}
impl sealed::Sealed for TokenStream {}
pub trait TokenTreeExt: Sized + sealed::Sealed {
fn equals(&self, other: &Self) -> bool;
fn is_group(&self) -> bool;
fn is_ident(&self) -> bool;
fn is_punct(&self) -> bool;
fn is_literal(&self) -> bool;
fn into_group(self) -> Result<Group, Self>;
fn into_ident(self) -> Result<Ident, Self>;
fn into_punct(self) -> Result<Punct, Self>;
fn into_literal(self) -> Result<Literal, Self>;
fn as_group(&self) -> Option<&Group>;
fn as_ident(&self) -> Option<&Ident>;
fn as_punct(&self) -> Option<&Punct>;
fn as_literal(&self) -> Option<&Literal>;
fn as_group_mut(&mut self) -> Option<&mut Group>;
fn as_ident_mut(&mut self) -> Option<&mut Ident>;
fn as_punct_mut(&mut self) -> Option<&mut Punct>;
fn as_literal_mut(&mut self) -> Option<&mut Literal>;
}
impl TokenTreeExt for TokenTree {
fn is_group(&self) -> bool {
matches!(self, Self::Group(_))
}
fn is_ident(&self) -> bool {
matches!(self, Self::Ident(_))
}
fn is_punct(&self) -> bool {
matches!(self, Self::Punct(_))
}
fn is_literal(&self) -> bool {
matches!(self, Self::Literal(_))
}
fn equals(&self, other: &Self) -> bool {
match (self, other) {
(Self::Group(this), Self::Group(other)) => this.equals(other),
(Self::Ident(this), Self::Ident(other)) => this.equals(other),
(Self::Punct(this), Self::Punct(other)) => this.equals(other),
(Self::Literal(this), Self::Literal(other)) => this.equals(other),
_ => false,
}
}
fn into_group(self) -> Result<Group, Self> {
match self {
Self::Group(group) => Ok(group),
_ => Err(self),
}
}
fn into_ident(self) -> Result<Ident, Self> {
match self {
Self::Ident(ident) => Ok(ident),
_ => Err(self),
}
}
fn into_punct(self) -> Result<Punct, Self> {
match self {
Self::Punct(punct) => Ok(punct),
_ => Err(self),
}
}
fn into_literal(self) -> Result<Literal, Self> {
match self {
Self::Literal(literal) => Ok(literal),
_ => Err(self),
}
}
fn as_group(&self) -> Option<&Group> {
match self {
Self::Group(group) => Some(group),
_ => None,
}
}
fn as_ident(&self) -> Option<&Ident> {
match self {
Self::Ident(ident) => Some(ident),
_ => None,
}
}
fn as_punct(&self) -> Option<&Punct> {
match self {
Self::Punct(punct) => Some(punct),
_ => None,
}
}
fn as_literal(&self) -> Option<&Literal> {
match self {
Self::Literal(literal) => Some(literal),
_ => None,
}
}
fn as_group_mut(&mut self) -> Option<&mut Group> {
match self {
Self::Group(group) => Some(group),
_ => None,
}
}
fn as_ident_mut(&mut self) -> Option<&mut Ident> {
match self {
Self::Ident(ident) => Some(ident),
_ => None,
}
}
fn as_punct_mut(&mut self) -> Option<&mut Punct> {
match self {
Self::Punct(punct) => Some(punct),
_ => None,
}
}
fn as_literal_mut(&mut self) -> Option<&mut Literal> {
match self {
Self::Literal(literal) => Some(literal),
_ => None,
}
}
}
impl sealed::Sealed for TokenTree {}
pub trait GroupExt: Sized + sealed::Sealed {
fn new_spanned(span: Span, delimiter: Delimiter, stream: TokenStream) -> Self;
fn equals(&self, other: &Self) -> bool;
fn is_delimiter(&self, delimiter: Delimiter) -> bool;
fn is_parenthesized(&self) -> bool;
fn is_braced(&self) -> bool;
fn is_bracketed(&self) -> bool;
fn is_undelimited(&self) -> bool;
}
impl GroupExt for Group {
fn new_spanned(span: Span, delimiter: Delimiter, stream: TokenStream) -> Self {
let mut group = Group::new(delimiter, stream);
group.set_span(span);
group
}
fn equals(&self, other: &Self) -> bool {
self.delimiter() == other.delimiter() && self.stream().equals(&other.stream())
}
fn is_delimiter(&self, delimiter: Delimiter) -> bool {
self.delimiter() == delimiter
}
fn is_parenthesized(&self) -> bool {
self.is_delimiter(Delimiter::Parenthesis)
}
fn is_braced(&self) -> bool {
self.is_delimiter(Delimiter::Brace)
}
fn is_bracketed(&self) -> bool {
self.is_delimiter(Delimiter::Bracket)
}
fn is_undelimited(&self) -> bool {
self.is_delimiter(Delimiter::None)
}
}
impl sealed::Sealed for Group {}
pub trait IdentExt: Sized + sealed::Sealed {
fn equals(&self, other: &Self) -> bool;
fn is_raw(&self) -> bool;
fn unraw(&self) -> Self;
}
impl IdentExt for Ident {
fn equals(&self, other: &Self) -> bool {
self == other
}
fn is_raw(&self) -> bool {
self.to_string().starts_with("r#")
}
fn unraw(&self) -> Self {
self.to_string()
.strip_prefix("r#")
.map_or_else(|| self.clone(), |stripped| Self::new(stripped, self.span()))
}
}
impl sealed::Sealed for Ident {}
pub trait PunctExt: Sized + sealed::Sealed {
fn new_spanned(span: Span, character: char, spacing: Spacing) -> Self;
fn equals(&self, other: &Self) -> bool;
fn is_char(&self, character: char) -> bool;
fn is_spacing(&self, spacing: Spacing) -> bool;
fn is_alone(&self) -> bool;
fn is_joint(&self) -> bool;
}
impl PunctExt for Punct {
fn new_spanned(span: Span, character: char, spacing: Spacing) -> Self {
let mut punct = Punct::new(character, spacing);
punct.set_span(span);
punct
}
fn equals(&self, other: &Self) -> bool {
self.as_char() == other.as_char() && self.spacing() == other.spacing()
}
fn is_char(&self, character: char) -> bool {
self.as_char() == character
}
fn is_spacing(&self, spacing: Spacing) -> bool {
self.spacing() == spacing
}
fn is_alone(&self) -> bool {
self.is_spacing(Spacing::Alone)
}
fn is_joint(&self) -> bool {
self.is_spacing(Spacing::Joint)
}
}
impl sealed::Sealed for Punct {}
pub trait LiteralExt: Sized + sealed::Sealed {
fn i8_suffixed_spanned(span: Span, integer: i8) -> Self;
fn i8_unsuffixed_spanned(span: Span, integer: i8) -> Self;
fn i16_suffixed_spanned(span: Span, integer: i16) -> Self;
fn i16_unsuffixed_spanned(span: Span, integer: i16) -> Self;
fn i32_suffixed_spanned(span: Span, integer: i32) -> Self;
fn i32_unsuffixed_spanned(span: Span, integer: i32) -> Self;
fn i64_suffixed_spanned(span: Span, integer: i64) -> Self;
fn i64_unsuffixed_spanned(span: Span, integer: i64) -> Self;
fn i128_suffixed_spanned(span: Span, integer: i128) -> Self;
fn i128_unsuffixed_spanned(span: Span, integer: i128) -> Self;
fn isize_suffixed_spanned(span: Span, integer: isize) -> Self;
fn isize_unsuffixed_spanned(span: Span, integer: isize) -> Self;
fn u8_suffixed_spanned(span: Span, integer: u8) -> Self;
fn u8_unsuffixed_spanned(span: Span, integer: u8) -> Self;
fn u16_suffixed_spanned(span: Span, integer: u16) -> Self;
fn u16_unsuffixed_spanned(span: Span, integer: u16) -> Self;
fn u32_suffixed_spanned(span: Span, integer: u32) -> Self;
fn u32_unsuffixed_spanned(span: Span, integer: u32) -> Self;
fn u64_suffixed_spanned(span: Span, integer: u64) -> Self;
fn u64_unsuffixed_spanned(span: Span, integer: u64) -> Self;
fn u128_suffixed_spanned(span: Span, integer: u128) -> Self;
fn u128_unsuffixed_spanned(span: Span, integer: u128) -> Self;
fn usize_suffixed_spanned(span: Span, integer: usize) -> Self;
fn usize_unsuffixed_spanned(span: Span, integer: usize) -> Self;
fn f32_suffixed_spanned(span: Span, float: f32) -> Self;
fn f32_unsuffixed_spanned(span: Span, float: f32) -> Self;
fn f64_suffixed_spanned(span: Span, float: f64) -> Self;
fn f64_unsuffixed_spanned(span: Span, float: f64) -> Self;
fn string_spanned(span: Span, string: &str) -> Self;
fn byte_string_spanned(span: Span, bytes: &[u8]) -> Self;
fn c_string_spanned(span: Span, string: &CStr) -> Self;
fn character_spanned(span: Span, character: char) -> Self;
fn byte_character_spanned(span: Span, byte: u8) -> Self;
fn equals(&self, other: &Self) -> bool;
}
impl LiteralExt for Literal {
fn i8_suffixed_spanned(span: Span, integer: i8) -> Self {
let mut literal = Self::i8_suffixed(integer);
literal.set_span(span);
literal
}
fn i8_unsuffixed_spanned(span: Span, integer: i8) -> Self {
let mut literal = Self::i8_unsuffixed(integer);
literal.set_span(span);
literal
}
fn i16_suffixed_spanned(span: Span, integer: i16) -> Self {
let mut literal = Self::i16_suffixed(integer);
literal.set_span(span);
literal
}
fn i16_unsuffixed_spanned(span: Span, integer: i16) -> Self {
let mut literal = Self::i16_unsuffixed(integer);
literal.set_span(span);
literal
}
fn i32_suffixed_spanned(span: Span, integer: i32) -> Self {
let mut literal = Self::i32_suffixed(integer);
literal.set_span(span);
literal
}
fn i32_unsuffixed_spanned(span: Span, integer: i32) -> Self {
let mut literal = Self::i32_unsuffixed(integer);
literal.set_span(span);
literal
}
fn i64_suffixed_spanned(span: Span, integer: i64) -> Self {
let mut literal = Self::i64_suffixed(integer);
literal.set_span(span);
literal
}
fn i64_unsuffixed_spanned(span: Span, integer: i64) -> Self {
let mut literal = Self::i64_unsuffixed(integer);
literal.set_span(span);
literal
}
fn i128_suffixed_spanned(span: Span, integer: i128) -> Self {
let mut literal = Self::i128_suffixed(integer);
literal.set_span(span);
literal
}
fn i128_unsuffixed_spanned(span: Span, integer: i128) -> Self {
let mut literal = Self::i128_unsuffixed(integer);
literal.set_span(span);
literal
}
fn isize_suffixed_spanned(span: Span, integer: isize) -> Self {
let mut literal = Self::isize_suffixed(integer);
literal.set_span(span);
literal
}
fn isize_unsuffixed_spanned(span: Span, integer: isize) -> Self {
let mut literal = Self::isize_unsuffixed(integer);
literal.set_span(span);
literal
}
fn u8_suffixed_spanned(span: Span, integer: u8) -> Self {
let mut literal = Self::u8_suffixed(integer);
literal.set_span(span);
literal
}
fn u8_unsuffixed_spanned(span: Span, integer: u8) -> Self {
let mut literal = Self::u8_unsuffixed(integer);
literal.set_span(span);
literal
}
fn u16_suffixed_spanned(span: Span, integer: u16) -> Self {
let mut literal = Self::u16_suffixed(integer);
literal.set_span(span);
literal
}
fn u16_unsuffixed_spanned(span: Span, integer: u16) -> Self {
let mut literal = Self::u16_unsuffixed(integer);
literal.set_span(span);
literal
}
fn u32_suffixed_spanned(span: Span, integer: u32) -> Self {
let mut literal = Self::u32_suffixed(integer);
literal.set_span(span);
literal
}
fn u32_unsuffixed_spanned(span: Span, integer: u32) -> Self {
let mut literal = Self::u32_unsuffixed(integer);
literal.set_span(span);
literal
}
fn u64_suffixed_spanned(span: Span, integer: u64) -> Self {
let mut literal = Self::u64_suffixed(integer);
literal.set_span(span);
literal
}
fn u64_unsuffixed_spanned(span: Span, integer: u64) -> Self {
let mut literal = Self::u64_unsuffixed(integer);
literal.set_span(span);
literal
}
fn u128_suffixed_spanned(span: Span, integer: u128) -> Self {
let mut literal = Self::u128_suffixed(integer);
literal.set_span(span);
literal
}
fn u128_unsuffixed_spanned(span: Span, integer: u128) -> Self {
let mut literal = Self::u128_unsuffixed(integer);
literal.set_span(span);
literal
}
fn usize_suffixed_spanned(span: Span, integer: usize) -> Self {
let mut literal = Self::usize_suffixed(integer);
literal.set_span(span);
literal
}
fn usize_unsuffixed_spanned(span: Span, integer: usize) -> Self {
let mut literal = Self::usize_unsuffixed(integer);
literal.set_span(span);
literal
}
fn f32_suffixed_spanned(span: Span, float: f32) -> Self {
let mut literal = Self::f32_suffixed(float);
literal.set_span(span);
literal
}
fn f32_unsuffixed_spanned(span: Span, float: f32) -> Self {
let mut literal = Self::f32_unsuffixed(float);
literal.set_span(span);
literal
}
fn f64_suffixed_spanned(span: Span, float: f64) -> Self {
let mut literal = Self::f64_suffixed(float);
literal.set_span(span);
literal
}
fn f64_unsuffixed_spanned(span: Span, float: f64) -> Self {
let mut literal = Self::f64_unsuffixed(float);
literal.set_span(span);
literal
}
fn string_spanned(span: Span, string: &str) -> Self {
let mut literal = Self::string(string);
literal.set_span(span);
literal
}
fn byte_string_spanned(span: Span, bytes: &[u8]) -> Self {
let mut literal = Self::byte_string(bytes);
literal.set_span(span);
literal
}
fn c_string_spanned(span: Span, string: &CStr) -> Self {
let mut literal = Self::c_string(string);
literal.set_span(span);
literal
}
fn character_spanned(span: Span, character: char) -> Self {
let mut literal = Self::character(character);
literal.set_span(span);
literal
}
fn byte_character_spanned(span: Span, byte: u8) -> Self {
let mut literal = Self::byte_character(byte);
literal.set_span(span);
literal
}
fn equals(&self, other: &Self) -> bool {
self.to_string() == other.to_string()
}
}
impl sealed::Sealed for Literal {}