170a21e54SGary Guo // SPDX-License-Identifier: Apache-2.0 OR MIT 270a21e54SGary Guo 370a21e54SGary Guo use proc_macro::{TokenStream, TokenTree}; 470a21e54SGary Guo 570a21e54SGary Guo pub(crate) trait ToTokens { to_tokens(&self, tokens: &mut TokenStream)670a21e54SGary Guo fn to_tokens(&self, tokens: &mut TokenStream); 770a21e54SGary Guo } 870a21e54SGary Guo 970a21e54SGary Guo impl<T: ToTokens> ToTokens for Option<T> { to_tokens(&self, tokens: &mut TokenStream)1070a21e54SGary Guo fn to_tokens(&self, tokens: &mut TokenStream) { 1170a21e54SGary Guo if let Some(v) = self { 1270a21e54SGary Guo v.to_tokens(tokens); 1370a21e54SGary Guo } 1470a21e54SGary Guo } 1570a21e54SGary Guo } 1670a21e54SGary Guo 1770a21e54SGary Guo impl ToTokens for proc_macro::Group { to_tokens(&self, tokens: &mut TokenStream)1870a21e54SGary Guo fn to_tokens(&self, tokens: &mut TokenStream) { 1970a21e54SGary Guo tokens.extend([TokenTree::from(self.clone())]); 2070a21e54SGary Guo } 2170a21e54SGary Guo } 2270a21e54SGary Guo 2370a21e54SGary Guo impl ToTokens for TokenTree { to_tokens(&self, tokens: &mut TokenStream)2470a21e54SGary Guo fn to_tokens(&self, tokens: &mut TokenStream) { 2570a21e54SGary Guo tokens.extend([self.clone()]); 2670a21e54SGary Guo } 2770a21e54SGary Guo } 2870a21e54SGary Guo 2970a21e54SGary Guo impl ToTokens for TokenStream { to_tokens(&self, tokens: &mut TokenStream)3070a21e54SGary Guo fn to_tokens(&self, tokens: &mut TokenStream) { 3170a21e54SGary Guo tokens.extend(self.clone()); 3270a21e54SGary Guo } 3370a21e54SGary Guo } 3470a21e54SGary Guo 3570a21e54SGary Guo /// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with 3670a21e54SGary Guo /// the given span. 3770a21e54SGary Guo /// 3870a21e54SGary Guo /// This is a similar to the 3970a21e54SGary Guo /// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the 4070a21e54SGary Guo /// `quote` crate but provides only just enough functionality needed by the current `macros` crate. 4170a21e54SGary Guo macro_rules! quote_spanned { 42b8342addSBenno Lossin ($span:expr => $($tt:tt)*) => {{ 43b8342addSBenno Lossin let mut tokens; 4470a21e54SGary Guo #[allow(clippy::vec_init_then_push)] 4570a21e54SGary Guo { 46b8342addSBenno Lossin tokens = ::std::vec::Vec::new(); 4770a21e54SGary Guo let span = $span; 4870a21e54SGary Guo quote_spanned!(@proc tokens span $($tt)*); 49b8342addSBenno Lossin } 5070a21e54SGary Guo ::proc_macro::TokenStream::from_iter(tokens) 5170a21e54SGary Guo }}; 5270a21e54SGary Guo (@proc $v:ident $span:ident) => {}; 5370a21e54SGary Guo (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => { 5470a21e54SGary Guo let mut ts = ::proc_macro::TokenStream::new(); 5570a21e54SGary Guo $crate::quote::ToTokens::to_tokens(&$id, &mut ts); 5670a21e54SGary Guo $v.extend(ts); 5770a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 5870a21e54SGary Guo }; 5970a21e54SGary Guo (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => { 6070a21e54SGary Guo for token in $id { 6170a21e54SGary Guo let mut ts = ::proc_macro::TokenStream::new(); 6270a21e54SGary Guo $crate::quote::ToTokens::to_tokens(&token, &mut ts); 6370a21e54SGary Guo $v.extend(ts); 6470a21e54SGary Guo } 6570a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 6670a21e54SGary Guo }; 6770a21e54SGary Guo (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => { 6870a21e54SGary Guo let mut tokens = ::std::vec::Vec::new(); 6970a21e54SGary Guo quote_spanned!(@proc tokens $span $($inner)*); 7070a21e54SGary Guo $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( 7170a21e54SGary Guo ::proc_macro::Delimiter::Parenthesis, 7270a21e54SGary Guo ::proc_macro::TokenStream::from_iter(tokens) 7370a21e54SGary Guo ))); 7470a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 7570a21e54SGary Guo }; 7670a21e54SGary Guo (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => { 7770a21e54SGary Guo let mut tokens = ::std::vec::Vec::new(); 7870a21e54SGary Guo quote_spanned!(@proc tokens $span $($inner)*); 7970a21e54SGary Guo $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( 8070a21e54SGary Guo ::proc_macro::Delimiter::Bracket, 8170a21e54SGary Guo ::proc_macro::TokenStream::from_iter(tokens) 8270a21e54SGary Guo ))); 8370a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 8470a21e54SGary Guo }; 8570a21e54SGary Guo (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => { 8670a21e54SGary Guo let mut tokens = ::std::vec::Vec::new(); 8770a21e54SGary Guo quote_spanned!(@proc tokens $span $($inner)*); 8870a21e54SGary Guo $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new( 8970a21e54SGary Guo ::proc_macro::Delimiter::Brace, 9070a21e54SGary Guo ::proc_macro::TokenStream::from_iter(tokens) 9170a21e54SGary Guo ))); 9270a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 9370a21e54SGary Guo }; 9470a21e54SGary Guo (@proc $v:ident $span:ident :: $($tt:tt)*) => { 9570a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 9670a21e54SGary Guo ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint) 9770a21e54SGary Guo )); 9870a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 9970a21e54SGary Guo ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) 10070a21e54SGary Guo )); 10170a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 10270a21e54SGary Guo }; 10370a21e54SGary Guo (@proc $v:ident $span:ident : $($tt:tt)*) => { 10470a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 10570a21e54SGary Guo ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone) 10670a21e54SGary Guo )); 10770a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 10870a21e54SGary Guo }; 10970a21e54SGary Guo (@proc $v:ident $span:ident , $($tt:tt)*) => { 11070a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 11170a21e54SGary Guo ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone) 11270a21e54SGary Guo )); 11370a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 11470a21e54SGary Guo }; 11570a21e54SGary Guo (@proc $v:ident $span:ident @ $($tt:tt)*) => { 11670a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 11770a21e54SGary Guo ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone) 11870a21e54SGary Guo )); 11970a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 12070a21e54SGary Guo }; 12170a21e54SGary Guo (@proc $v:ident $span:ident ! $($tt:tt)*) => { 12270a21e54SGary Guo $v.push(::proc_macro::TokenTree::Punct( 12370a21e54SGary Guo ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone) 12470a21e54SGary Guo )); 12570a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 12670a21e54SGary Guo }; 127*071cedc8SBenno Lossin (@proc $v:ident $span:ident ; $($tt:tt)*) => { 128*071cedc8SBenno Lossin $v.push(::proc_macro::TokenTree::Punct( 129*071cedc8SBenno Lossin ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone) 130*071cedc8SBenno Lossin )); 131*071cedc8SBenno Lossin quote_spanned!(@proc $v $span $($tt)*); 132*071cedc8SBenno Lossin }; 133*071cedc8SBenno Lossin (@proc $v:ident $span:ident + $($tt:tt)*) => { 134*071cedc8SBenno Lossin $v.push(::proc_macro::TokenTree::Punct( 135*071cedc8SBenno Lossin ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone) 136*071cedc8SBenno Lossin )); 137*071cedc8SBenno Lossin quote_spanned!(@proc $v $span $($tt)*); 138*071cedc8SBenno Lossin }; 13970a21e54SGary Guo (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => { 14070a21e54SGary Guo $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span))); 14170a21e54SGary Guo quote_spanned!(@proc $v $span $($tt)*); 14270a21e54SGary Guo }; 14370a21e54SGary Guo } 14470a21e54SGary Guo 14570a21e54SGary Guo /// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with 14670a21e54SGary Guo /// mixed site span ([`Span::mixed_site()`]). 14770a21e54SGary Guo /// 14870a21e54SGary Guo /// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro 14970a21e54SGary Guo /// from the `quote` crate but provides only just enough functionality needed by the current 15070a21e54SGary Guo /// `macros` crate. 15170a21e54SGary Guo /// 15270a21e54SGary Guo /// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site 15370a21e54SGary Guo macro_rules! quote { 15470a21e54SGary Guo ($($tt:tt)*) => { 15570a21e54SGary Guo quote_spanned!(::proc_macro::Span::mixed_site() => $($tt)*) 15670a21e54SGary Guo } 15770a21e54SGary Guo } 158