162306a36Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 OR MIT
262306a36Sopenharmony_ci
362306a36Sopenharmony_ciuse proc_macro::{TokenStream, TokenTree};
462306a36Sopenharmony_ci
562306a36Sopenharmony_cipub(crate) trait ToTokens {
662306a36Sopenharmony_ci    fn to_tokens(&self, tokens: &mut TokenStream);
762306a36Sopenharmony_ci}
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciimpl<T: ToTokens> ToTokens for Option<T> {
1062306a36Sopenharmony_ci    fn to_tokens(&self, tokens: &mut TokenStream) {
1162306a36Sopenharmony_ci        if let Some(v) = self {
1262306a36Sopenharmony_ci            v.to_tokens(tokens);
1362306a36Sopenharmony_ci        }
1462306a36Sopenharmony_ci    }
1562306a36Sopenharmony_ci}
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ciimpl ToTokens for proc_macro::Group {
1862306a36Sopenharmony_ci    fn to_tokens(&self, tokens: &mut TokenStream) {
1962306a36Sopenharmony_ci        tokens.extend([TokenTree::from(self.clone())]);
2062306a36Sopenharmony_ci    }
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ciimpl ToTokens for TokenTree {
2462306a36Sopenharmony_ci    fn to_tokens(&self, tokens: &mut TokenStream) {
2562306a36Sopenharmony_ci        tokens.extend([self.clone()]);
2662306a36Sopenharmony_ci    }
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciimpl ToTokens for TokenStream {
3062306a36Sopenharmony_ci    fn to_tokens(&self, tokens: &mut TokenStream) {
3162306a36Sopenharmony_ci        tokens.extend(self.clone());
3262306a36Sopenharmony_ci    }
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
3662306a36Sopenharmony_ci/// the given span.
3762306a36Sopenharmony_ci///
3862306a36Sopenharmony_ci/// This is a similar to the
3962306a36Sopenharmony_ci/// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the
4062306a36Sopenharmony_ci/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
4162306a36Sopenharmony_cimacro_rules! quote_spanned {
4262306a36Sopenharmony_ci    ($span:expr => $($tt:tt)*) => {{
4362306a36Sopenharmony_ci        let mut tokens;
4462306a36Sopenharmony_ci        #[allow(clippy::vec_init_then_push)]
4562306a36Sopenharmony_ci        {
4662306a36Sopenharmony_ci            tokens = ::std::vec::Vec::new();
4762306a36Sopenharmony_ci            let span = $span;
4862306a36Sopenharmony_ci            quote_spanned!(@proc tokens span $($tt)*);
4962306a36Sopenharmony_ci        }
5062306a36Sopenharmony_ci        ::proc_macro::TokenStream::from_iter(tokens)
5162306a36Sopenharmony_ci    }};
5262306a36Sopenharmony_ci    (@proc $v:ident $span:ident) => {};
5362306a36Sopenharmony_ci    (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
5462306a36Sopenharmony_ci        let mut ts = ::proc_macro::TokenStream::new();
5562306a36Sopenharmony_ci        $crate::quote::ToTokens::to_tokens(&$id, &mut ts);
5662306a36Sopenharmony_ci        $v.extend(ts);
5762306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
5862306a36Sopenharmony_ci    };
5962306a36Sopenharmony_ci    (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
6062306a36Sopenharmony_ci        for token in $id {
6162306a36Sopenharmony_ci            let mut ts = ::proc_macro::TokenStream::new();
6262306a36Sopenharmony_ci            $crate::quote::ToTokens::to_tokens(&token, &mut ts);
6362306a36Sopenharmony_ci            $v.extend(ts);
6462306a36Sopenharmony_ci        }
6562306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
6662306a36Sopenharmony_ci    };
6762306a36Sopenharmony_ci    (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
6862306a36Sopenharmony_ci        let mut tokens = ::std::vec::Vec::new();
6962306a36Sopenharmony_ci        quote_spanned!(@proc tokens $span $($inner)*);
7062306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
7162306a36Sopenharmony_ci            ::proc_macro::Delimiter::Parenthesis,
7262306a36Sopenharmony_ci            ::proc_macro::TokenStream::from_iter(tokens)
7362306a36Sopenharmony_ci        )));
7462306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
7562306a36Sopenharmony_ci    };
7662306a36Sopenharmony_ci    (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
7762306a36Sopenharmony_ci        let mut tokens = ::std::vec::Vec::new();
7862306a36Sopenharmony_ci        quote_spanned!(@proc tokens $span $($inner)*);
7962306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
8062306a36Sopenharmony_ci            ::proc_macro::Delimiter::Bracket,
8162306a36Sopenharmony_ci            ::proc_macro::TokenStream::from_iter(tokens)
8262306a36Sopenharmony_ci        )));
8362306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
8462306a36Sopenharmony_ci    };
8562306a36Sopenharmony_ci    (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
8662306a36Sopenharmony_ci        let mut tokens = ::std::vec::Vec::new();
8762306a36Sopenharmony_ci        quote_spanned!(@proc tokens $span $($inner)*);
8862306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
8962306a36Sopenharmony_ci            ::proc_macro::Delimiter::Brace,
9062306a36Sopenharmony_ci            ::proc_macro::TokenStream::from_iter(tokens)
9162306a36Sopenharmony_ci        )));
9262306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
9362306a36Sopenharmony_ci    };
9462306a36Sopenharmony_ci    (@proc $v:ident $span:ident :: $($tt:tt)*) => {
9562306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
9662306a36Sopenharmony_ci                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint)
9762306a36Sopenharmony_ci        ));
9862306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
9962306a36Sopenharmony_ci                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
10062306a36Sopenharmony_ci        ));
10162306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
10262306a36Sopenharmony_ci    };
10362306a36Sopenharmony_ci    (@proc $v:ident $span:ident : $($tt:tt)*) => {
10462306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
10562306a36Sopenharmony_ci                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
10662306a36Sopenharmony_ci        ));
10762306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
10862306a36Sopenharmony_ci    };
10962306a36Sopenharmony_ci    (@proc $v:ident $span:ident , $($tt:tt)*) => {
11062306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
11162306a36Sopenharmony_ci                ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone)
11262306a36Sopenharmony_ci        ));
11362306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
11462306a36Sopenharmony_ci    };
11562306a36Sopenharmony_ci    (@proc $v:ident $span:ident @ $($tt:tt)*) => {
11662306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
11762306a36Sopenharmony_ci                ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone)
11862306a36Sopenharmony_ci        ));
11962306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
12062306a36Sopenharmony_ci    };
12162306a36Sopenharmony_ci    (@proc $v:ident $span:ident ! $($tt:tt)*) => {
12262306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
12362306a36Sopenharmony_ci                ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone)
12462306a36Sopenharmony_ci        ));
12562306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
12662306a36Sopenharmony_ci    };
12762306a36Sopenharmony_ci    (@proc $v:ident $span:ident ; $($tt:tt)*) => {
12862306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
12962306a36Sopenharmony_ci                ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone)
13062306a36Sopenharmony_ci        ));
13162306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
13262306a36Sopenharmony_ci    };
13362306a36Sopenharmony_ci    (@proc $v:ident $span:ident + $($tt:tt)*) => {
13462306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Punct(
13562306a36Sopenharmony_ci                ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone)
13662306a36Sopenharmony_ci        ));
13762306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
13862306a36Sopenharmony_ci    };
13962306a36Sopenharmony_ci    (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
14062306a36Sopenharmony_ci        $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span)));
14162306a36Sopenharmony_ci        quote_spanned!(@proc $v $span $($tt)*);
14262306a36Sopenharmony_ci    };
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
14662306a36Sopenharmony_ci/// mixed site span ([`Span::mixed_site()`]).
14762306a36Sopenharmony_ci///
14862306a36Sopenharmony_ci/// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro
14962306a36Sopenharmony_ci/// from the `quote` crate but provides only just enough functionality needed by the current
15062306a36Sopenharmony_ci/// `macros` crate.
15162306a36Sopenharmony_ci///
15262306a36Sopenharmony_ci/// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site
15362306a36Sopenharmony_cimacro_rules! quote {
15462306a36Sopenharmony_ci    ($($tt:tt)*) => {
15562306a36Sopenharmony_ci        quote_spanned!(::proc_macro::Span::mixed_site() => $($tt)*)
15662306a36Sopenharmony_ci    }
15762306a36Sopenharmony_ci}
158