Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: Apache-2.0 OR MIT
  2
  3use proc_macro::{TokenStream, TokenTree};
  4
  5pub(crate) trait ToTokens {
  6    fn to_tokens(&self, tokens: &mut TokenStream);
  7}
  8
  9impl<T: ToTokens> ToTokens for Option<T> {
 10    fn to_tokens(&self, tokens: &mut TokenStream) {
 11        if let Some(v) = self {
 12            v.to_tokens(tokens);
 13        }
 14    }
 15}
 16
 17impl ToTokens for proc_macro::Group {
 18    fn to_tokens(&self, tokens: &mut TokenStream) {
 19        tokens.extend([TokenTree::from(self.clone())]);
 20    }
 21}
 22
 23impl ToTokens for TokenTree {
 24    fn to_tokens(&self, tokens: &mut TokenStream) {
 25        tokens.extend([self.clone()]);
 26    }
 27}
 28
 29impl ToTokens for TokenStream {
 30    fn to_tokens(&self, tokens: &mut TokenStream) {
 31        tokens.extend(self.clone());
 32    }
 33}
 34
 35/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
 36/// the given span.
 37///
 38/// This is a similar to the
 39/// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the
 40/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
 41macro_rules! quote_spanned {
 42    ($span:expr => $($tt:tt)*) => {{
 43        let mut tokens;
 44        #[allow(clippy::vec_init_then_push)]
 45        {
 46            tokens = ::std::vec::Vec::new();
 47            let span = $span;
 48            quote_spanned!(@proc tokens span $($tt)*);
 49        }
 50        ::proc_macro::TokenStream::from_iter(tokens)
 51    }};
 52    (@proc $v:ident $span:ident) => {};
 53    (@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
 54        let mut ts = ::proc_macro::TokenStream::new();
 55        $crate::quote::ToTokens::to_tokens(&$id, &mut ts);
 56        $v.extend(ts);
 57        quote_spanned!(@proc $v $span $($tt)*);
 58    };
 59    (@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
 60        for token in $id {
 61            let mut ts = ::proc_macro::TokenStream::new();
 62            $crate::quote::ToTokens::to_tokens(&token, &mut ts);
 63            $v.extend(ts);
 64        }
 65        quote_spanned!(@proc $v $span $($tt)*);
 66    };
 67    (@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
 68        let mut tokens = ::std::vec::Vec::new();
 69        quote_spanned!(@proc tokens $span $($inner)*);
 70        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 71            ::proc_macro::Delimiter::Parenthesis,
 72            ::proc_macro::TokenStream::from_iter(tokens)
 73        )));
 74        quote_spanned!(@proc $v $span $($tt)*);
 75    };
 76    (@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
 77        let mut tokens = ::std::vec::Vec::new();
 78        quote_spanned!(@proc tokens $span $($inner)*);
 79        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 80            ::proc_macro::Delimiter::Bracket,
 81            ::proc_macro::TokenStream::from_iter(tokens)
 82        )));
 83        quote_spanned!(@proc $v $span $($tt)*);
 84    };
 85    (@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
 86        let mut tokens = ::std::vec::Vec::new();
 87        quote_spanned!(@proc tokens $span $($inner)*);
 88        $v.push(::proc_macro::TokenTree::Group(::proc_macro::Group::new(
 89            ::proc_macro::Delimiter::Brace,
 90            ::proc_macro::TokenStream::from_iter(tokens)
 91        )));
 92        quote_spanned!(@proc $v $span $($tt)*);
 93    };
 94    (@proc $v:ident $span:ident :: $($tt:tt)*) => {
 95        $v.push(::proc_macro::TokenTree::Punct(
 96                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Joint)
 97        ));
 98        $v.push(::proc_macro::TokenTree::Punct(
 99                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
100        ));
101        quote_spanned!(@proc $v $span $($tt)*);
102    };
103    (@proc $v:ident $span:ident : $($tt:tt)*) => {
104        $v.push(::proc_macro::TokenTree::Punct(
105                ::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone)
106        ));
107        quote_spanned!(@proc $v $span $($tt)*);
108    };
109    (@proc $v:ident $span:ident , $($tt:tt)*) => {
110        $v.push(::proc_macro::TokenTree::Punct(
111                ::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone)
112        ));
113        quote_spanned!(@proc $v $span $($tt)*);
114    };
115    (@proc $v:ident $span:ident @ $($tt:tt)*) => {
116        $v.push(::proc_macro::TokenTree::Punct(
117                ::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone)
118        ));
119        quote_spanned!(@proc $v $span $($tt)*);
120    };
121    (@proc $v:ident $span:ident ! $($tt:tt)*) => {
122        $v.push(::proc_macro::TokenTree::Punct(
123                ::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone)
124        ));
125        quote_spanned!(@proc $v $span $($tt)*);
126    };
127    (@proc $v:ident $span:ident ; $($tt:tt)*) => {
128        $v.push(::proc_macro::TokenTree::Punct(
129                ::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone)
130        ));
131        quote_spanned!(@proc $v $span $($tt)*);
132    };
133    (@proc $v:ident $span:ident + $($tt:tt)*) => {
134        $v.push(::proc_macro::TokenTree::Punct(
135                ::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone)
136        ));
137        quote_spanned!(@proc $v $span $($tt)*);
138    };
139    (@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
140        $v.push(::proc_macro::TokenTree::Ident(::proc_macro::Ident::new(stringify!($id), $span)));
141        quote_spanned!(@proc $v $span $($tt)*);
142    };
143}
144
145/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
146/// mixed site span ([`Span::mixed_site()`]).
147///
148/// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro
149/// from the `quote` crate but provides only just enough functionality needed by the current
150/// `macros` crate.
151///
152/// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site
153macro_rules! quote {
154    ($($tt:tt)*) => {
155        quote_spanned!(::proc_macro::Span::mixed_site() => $($tt)*)
156    }
157}