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            for (i, token) in iter.into_iter().enumerate() {
100                if i > 0 {
101                    op.to_tokens(stream);
102                }
103                token.to_tokens(stream);
104            }
105        }
106    }
107
108    fn append_terminated<I, U>(&mut self, iter: I, term: U)
109    where
110        I: IntoIterator,
111        I::Item: ToTokens,
112        U: ToTokens,
113    {
114        do_append_terminated(self, iter.into_iter(), term);
115
116        fn do_append_terminated<I, U>(stream: &mut TokenStream, iter: I, term: U)
117        where
118            I: Iterator,
119            I::Item: ToTokens,
120            U: ToTokens,
121        {
122            for token in iter {
123                token.to_tokens(stream);
124                term.to_tokens(stream);
125            }
126        }
127    }
128}
129
130mod private {
131    use proc_macro2::TokenStream;
132
133    pub trait Sealed {}
134
135    impl Sealed for TokenStream {}
136}