quote/
to_tokens.rs

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