rune/macros/
quote_fn.rs

1use core::fmt;
2
3use crate::alloc;
4use crate::macros::{MacroContext, ToTokens, TokenStream};
5
6type EncodeFn<'a> =
7    dyn Fn(&mut MacroContext<'_, '_, '_>, &mut TokenStream) -> alloc::Result<()> + Send + Sync + 'a;
8
9/// Construct a token stream from a function.
10pub fn quote_fn<'a, T>(f: T) -> Quote<'a>
11where
12    T: 'a + Fn(&mut MacroContext<'_, '_, '_>, &mut TokenStream) -> alloc::Result<()> + Send + Sync,
13{
14    // TODO: somehow support CoerceUnsized.
15    Quote(rust_alloc::boxed::Box::new(f))
16}
17
18/// [ToTokens] implementation generated by [quote_fn].
19pub struct Quote<'a>(rust_alloc::boxed::Box<EncodeFn<'a>>);
20
21impl Quote<'_> {
22    /// Convert into token stream.
23    ///
24    /// # Panics
25    ///
26    /// This panics if called outside of a macro context.
27    pub fn into_token_stream(
28        self,
29        cx: &mut MacroContext<'_, '_, '_>,
30    ) -> alloc::Result<TokenStream> {
31        let mut stream = TokenStream::new();
32        self.to_tokens(cx, &mut stream)?;
33        Ok(stream)
34    }
35}
36
37impl ToTokens for Quote<'_> {
38    fn to_tokens(
39        &self,
40        context: &mut MacroContext<'_, '_, '_>,
41        stream: &mut TokenStream,
42    ) -> alloc::Result<()> {
43        (self.0)(context, stream)
44    }
45}
46
47impl fmt::Debug for Quote<'_> {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.debug_tuple("Quote").finish()
50    }
51}