quote/
ext.rs

1use super::ToTokens;
2use core::iter;
3use proc_macro2::{TokenStream, TokenTree};
4
5/// TokenStream extension trait with methods for appending tokens.
6///
7/// This trait is sealed and cannot be implemented outside of the `quote` crate.
8pub trait TokenStreamExt: private::Sealed {
9    /// For use by `ToTokens` implementations.
10    ///
11    /// Appends the token specified to this list of tokens.
12    fn append<U>(&mut self, token: U)
13    where
14        U: Into<TokenTree>;
15
16    /// For use by `ToTokens` implementations.
17    ///
18    /// ```
19    /// # use quote::{quote, TokenStreamExt, ToTokens};
20    /// # use proc_macro2::TokenStream;
21    /// #
22    /// struct X;
23    ///
24    /// impl ToTokens for X {
25    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
26    ///         tokens.append_all(&[true, false]);
27    ///     }
28    /// }
29    ///
30    /// let tokens = quote!(#X);
31    /// assert_eq!(tokens.to_string(), "true false");
32    /// ```
33    fn append_all<I>(&mut self, iter: I)
34    where
35        I: IntoIterator,
36        I::Item: ToTokens;
37
38    /// For use by `ToTokens` implementations.
39    ///
40    /// Appends all of the items in the iterator `I`, separated by the tokens
41    /// `U`.
42    fn append_separated<I, U>(&mut self, iter: I, op: U)
43    where
44        I: IntoIterator,
45        I::Item: ToTokens,
46        U: ToTokens;
47
48    /// For use by `ToTokens` implementations.
49    ///
50    /// Appends all tokens in the iterator `I`, appending `U` after each
51    /// element, including after the last element of the iterator.
52    fn append_terminated<I, U>(&mut self, iter: I, term: U)
53    where
54        I: IntoIterator,
55        I::Item: ToTokens,
56        U: ToTokens;
57}
58
59impl TokenStreamExt for TokenStream {
60    fn append<U>(&mut self, token: U)
61    where
62        U: Into<TokenTree>,
63    {
64        self.extend(iter::once(token.into()));
65    }
66
67    fn append_all<I>(&mut self, iter: I)
68    where
69        I: IntoIterator,
70        I::Item: ToTokens,
71    {
72        do_append_all(self, iter.into_iter());
73
74        fn do_append_all<I>(stream: &mut TokenStream, iter: I)
75        where
76            I: Iterator,
77            I::Item: ToTokens,
78        {
79            for token in iter {
80                token.to_tokens(stream);
81            }
82        }
83    }
84
85    fn append_separated<I, U>(&mut self, iter: I, op: U)
86    where
87        I: IntoIterator,
88        I::Item: ToTokens,
89        U: ToTokens,
90    {
91        do_append_separated(self, iter.into_iter(), op);
92
93        fn do_append_separated<I, U>(stream: &mut TokenStream, iter: I, op: U)
94        where
95            I: Iterator,
96            I::Item: ToTokens,
97            U: ToTokens,
98        {
99            let mut first = true;
100            for token in iter {
101                if !first {
102                    op.to_tokens(stream);
103                }
104                first = false;
105                token.to_tokens(stream);
106            }
107        }
108    }
109
110    fn append_terminated<I, U>(&mut self, iter: I, term: U)
111    where
112        I: IntoIterator,
113        I::Item: ToTokens,
114        U: ToTokens,
115    {
116        do_append_terminated(self, iter.into_iter(), term);
117
118        fn do_append_terminated<I, U>(stream: &mut TokenStream, iter: I, term: U)
119        where
120            I: Iterator,
121            I::Item: ToTokens,
122            U: ToTokens,
123        {
124            for token in iter {
125                token.to_tokens(stream);
126                term.to_tokens(stream);
127            }
128        }
129    }
130}
131
132mod private {
133    use proc_macro2::TokenStream;
134
135    pub trait Sealed {}
136
137    impl Sealed for TokenStream {}
138}