quote/
to_tokens.rs

1use super::TokenStreamExt;
2use alloc::borrow::{Cow, ToOwned};
3use alloc::boxed::Box;
4use alloc::ffi::CString;
5use alloc::rc::Rc;
6use alloc::string::String;
7use core::ffi::CStr;
8use core::iter;
9use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
10
11/// Types that can be interpolated inside a `quote!` invocation.
12pub trait ToTokens {
13    /// Write `self` to the given `TokenStream`.
14    ///
15    /// The token append methods provided by the [`TokenStreamExt`] extension
16    /// trait may be useful for implementing `ToTokens`.
17    ///
18    /// # Example
19    ///
20    /// Example implementation for a struct representing Rust paths like
21    /// `std::cmp::PartialEq`:
22    ///
23    /// ```
24    /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
25    /// use quote::{TokenStreamExt, ToTokens};
26    ///
27    /// pub struct Path {
28    ///     pub global: bool,
29    ///     pub segments: Vec<PathSegment>,
30    /// }
31    ///
32    /// impl ToTokens for Path {
33    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
34    ///         for (i, segment) in self.segments.iter().enumerate() {
35    ///             if i > 0 || self.global {
36    ///                 // Double colon `::`
37    ///                 tokens.append(Punct::new(':', Spacing::Joint));
38    ///                 tokens.append(Punct::new(':', Spacing::Alone));
39    ///             }
40    ///             segment.to_tokens(tokens);
41    ///         }
42    ///     }
43    /// }
44    /// #
45    /// # pub struct PathSegment;
46    /// #
47    /// # impl ToTokens for PathSegment {
48    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
49    /// #         unimplemented!()
50    /// #     }
51    /// # }
52    /// ```
53    fn to_tokens(&self, tokens: &mut TokenStream);
54
55    /// Convert `self` directly into a `TokenStream` object.
56    ///
57    /// This method is implicitly implemented using `to_tokens`, and acts as a
58    /// convenience method for consumers of the `ToTokens` trait.
59    fn to_token_stream(&self) -> TokenStream {
60        let mut tokens = TokenStream::new();
61        self.to_tokens(&mut tokens);
62        tokens
63    }
64
65    /// Convert `self` directly into a `TokenStream` object.
66    ///
67    /// This method is implicitly implemented using `to_tokens`, and acts as a
68    /// convenience method for consumers of the `ToTokens` trait.
69    fn into_token_stream(self) -> TokenStream
70    where
71        Self: Sized,
72    {
73        self.to_token_stream()
74    }
75}
76
77impl<T: ?Sized + ToTokens> ToTokens for &T {
78    fn to_tokens(&self, tokens: &mut TokenStream) {
79        (**self).to_tokens(tokens);
80    }
81}
82
83impl<T: ?Sized + ToTokens> ToTokens for &mut T {
84    fn to_tokens(&self, tokens: &mut TokenStream) {
85        (**self).to_tokens(tokens);
86    }
87}
88
89impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
90    fn to_tokens(&self, tokens: &mut TokenStream) {
91        (**self).to_tokens(tokens);
92    }
93}
94
95impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
96    fn to_tokens(&self, tokens: &mut TokenStream) {
97        (**self).to_tokens(tokens);
98    }
99}
100
101impl<T: ?Sized + ToTokens> ToTokens for Rc<T> {
102    fn to_tokens(&self, tokens: &mut TokenStream) {
103        (**self).to_tokens(tokens);
104    }
105}
106
107impl<T: ToTokens> ToTokens for Option<T> {
108    fn to_tokens(&self, tokens: &mut TokenStream) {
109        if let Some(t) = self {
110            t.to_tokens(tokens);
111        }
112    }
113}
114
115impl ToTokens for str {
116    fn to_tokens(&self, tokens: &mut TokenStream) {
117        tokens.append(Literal::string(self));
118    }
119}
120
121impl ToTokens for String {
122    fn to_tokens(&self, tokens: &mut TokenStream) {
123        self.as_str().to_tokens(tokens);
124    }
125}
126
127impl ToTokens for i8 {
128    fn to_tokens(&self, tokens: &mut TokenStream) {
129        tokens.append(Literal::i8_suffixed(*self));
130    }
131}
132
133impl ToTokens for i16 {
134    fn to_tokens(&self, tokens: &mut TokenStream) {
135        tokens.append(Literal::i16_suffixed(*self));
136    }
137}
138
139impl ToTokens for i32 {
140    fn to_tokens(&self, tokens: &mut TokenStream) {
141        tokens.append(Literal::i32_suffixed(*self));
142    }
143}
144
145impl ToTokens for i64 {
146    fn to_tokens(&self, tokens: &mut TokenStream) {
147        tokens.append(Literal::i64_suffixed(*self));
148    }
149}
150
151impl ToTokens for i128 {
152    fn to_tokens(&self, tokens: &mut TokenStream) {
153        tokens.append(Literal::i128_suffixed(*self));
154    }
155}
156
157impl ToTokens for isize {
158    fn to_tokens(&self, tokens: &mut TokenStream) {
159        tokens.append(Literal::isize_suffixed(*self));
160    }
161}
162
163impl ToTokens for u8 {
164    fn to_tokens(&self, tokens: &mut TokenStream) {
165        tokens.append(Literal::u8_suffixed(*self));
166    }
167}
168
169impl ToTokens for u16 {
170    fn to_tokens(&self, tokens: &mut TokenStream) {
171        tokens.append(Literal::u16_suffixed(*self));
172    }
173}
174
175impl ToTokens for u32 {
176    fn to_tokens(&self, tokens: &mut TokenStream) {
177        tokens.append(Literal::u32_suffixed(*self));
178    }
179}
180
181impl ToTokens for u64 {
182    fn to_tokens(&self, tokens: &mut TokenStream) {
183        tokens.append(Literal::u64_suffixed(*self));
184    }
185}
186
187impl ToTokens for u128 {
188    fn to_tokens(&self, tokens: &mut TokenStream) {
189        tokens.append(Literal::u128_suffixed(*self));
190    }
191}
192
193impl ToTokens for usize {
194    fn to_tokens(&self, tokens: &mut TokenStream) {
195        tokens.append(Literal::usize_suffixed(*self));
196    }
197}
198
199impl ToTokens for f32 {
200    fn to_tokens(&self, tokens: &mut TokenStream) {
201        tokens.append(Literal::f32_suffixed(*self));
202    }
203}
204
205impl ToTokens for f64 {
206    fn to_tokens(&self, tokens: &mut TokenStream) {
207        tokens.append(Literal::f64_suffixed(*self));
208    }
209}
210
211impl ToTokens for char {
212    fn to_tokens(&self, tokens: &mut TokenStream) {
213        tokens.append(Literal::character(*self));
214    }
215}
216
217impl ToTokens for bool {
218    fn to_tokens(&self, tokens: &mut TokenStream) {
219        let word = if *self { "true" } else { "false" };
220        tokens.append(Ident::new(word, Span::call_site()));
221    }
222}
223
224impl ToTokens for CStr {
225    fn to_tokens(&self, tokens: &mut TokenStream) {
226        tokens.append(Literal::c_string(self));
227    }
228}
229
230impl ToTokens for CString {
231    fn to_tokens(&self, tokens: &mut TokenStream) {
232        tokens.append(Literal::c_string(self));
233    }
234}
235
236impl ToTokens for Group {
237    fn to_tokens(&self, tokens: &mut TokenStream) {
238        tokens.append(self.clone());
239    }
240}
241
242impl ToTokens for Ident {
243    fn to_tokens(&self, tokens: &mut TokenStream) {
244        tokens.append(self.clone());
245    }
246}
247
248impl ToTokens for Punct {
249    fn to_tokens(&self, tokens: &mut TokenStream) {
250        tokens.append(self.clone());
251    }
252}
253
254impl ToTokens for Literal {
255    fn to_tokens(&self, tokens: &mut TokenStream) {
256        tokens.append(self.clone());
257    }
258}
259
260impl ToTokens for TokenTree {
261    fn to_tokens(&self, tokens: &mut TokenStream) {
262        tokens.append(self.clone());
263    }
264}
265
266impl ToTokens for TokenStream {
267    fn to_tokens(&self, tokens: &mut TokenStream) {
268        tokens.extend(iter::once(self.clone()));
269    }
270
271    fn into_token_stream(self) -> TokenStream {
272        self
273    }
274}