quote/
to_tokens.rs

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