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.
9///
10/// [`quote!`]: macro.quote.html
11pub trait ToTokens {
12    /// Write `self` to the given `TokenStream`.
13    ///
14    /// The token append methods provided by the [`TokenStreamExt`] extension
15    /// trait may be useful for implementing `ToTokens`.
16    ///
17    /// [`TokenStreamExt`]: trait.TokenStreamExt.html
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: ToTokens> ToTokens for Option<T> {
109    fn to_tokens(&self, tokens: &mut TokenStream) {
110        if let Some(t) = self {
111            t.to_tokens(tokens);
112        }
113    }
114}
115
116impl ToTokens for str {
117    fn to_tokens(&self, tokens: &mut TokenStream) {
118        tokens.append(Literal::string(self));
119    }
120}
121
122impl ToTokens for String {
123    fn to_tokens(&self, tokens: &mut TokenStream) {
124        self.as_str().to_tokens(tokens);
125    }
126}
127
128impl ToTokens for i8 {
129    fn to_tokens(&self, tokens: &mut TokenStream) {
130        tokens.append(Literal::i8_suffixed(*self));
131    }
132}
133
134impl ToTokens for i16 {
135    fn to_tokens(&self, tokens: &mut TokenStream) {
136        tokens.append(Literal::i16_suffixed(*self));
137    }
138}
139
140impl ToTokens for i32 {
141    fn to_tokens(&self, tokens: &mut TokenStream) {
142        tokens.append(Literal::i32_suffixed(*self));
143    }
144}
145
146impl ToTokens for i64 {
147    fn to_tokens(&self, tokens: &mut TokenStream) {
148        tokens.append(Literal::i64_suffixed(*self));
149    }
150}
151
152impl ToTokens for i128 {
153    fn to_tokens(&self, tokens: &mut TokenStream) {
154        tokens.append(Literal::i128_suffixed(*self));
155    }
156}
157
158impl ToTokens for isize {
159    fn to_tokens(&self, tokens: &mut TokenStream) {
160        tokens.append(Literal::isize_suffixed(*self));
161    }
162}
163
164impl ToTokens for u8 {
165    fn to_tokens(&self, tokens: &mut TokenStream) {
166        tokens.append(Literal::u8_suffixed(*self));
167    }
168}
169
170impl ToTokens for u16 {
171    fn to_tokens(&self, tokens: &mut TokenStream) {
172        tokens.append(Literal::u16_suffixed(*self));
173    }
174}
175
176impl ToTokens for u32 {
177    fn to_tokens(&self, tokens: &mut TokenStream) {
178        tokens.append(Literal::u32_suffixed(*self));
179    }
180}
181
182impl ToTokens for u64 {
183    fn to_tokens(&self, tokens: &mut TokenStream) {
184        tokens.append(Literal::u64_suffixed(*self));
185    }
186}
187
188impl ToTokens for u128 {
189    fn to_tokens(&self, tokens: &mut TokenStream) {
190        tokens.append(Literal::u128_suffixed(*self));
191    }
192}
193
194impl ToTokens for usize {
195    fn to_tokens(&self, tokens: &mut TokenStream) {
196        tokens.append(Literal::usize_suffixed(*self));
197    }
198}
199
200impl ToTokens for f32 {
201    fn to_tokens(&self, tokens: &mut TokenStream) {
202        tokens.append(Literal::f32_suffixed(*self));
203    }
204}
205
206impl ToTokens for f64 {
207    fn to_tokens(&self, tokens: &mut TokenStream) {
208        tokens.append(Literal::f64_suffixed(*self));
209    }
210}
211
212impl ToTokens for char {
213    fn to_tokens(&self, tokens: &mut TokenStream) {
214        tokens.append(Literal::character(*self));
215    }
216}
217
218impl ToTokens for bool {
219    fn to_tokens(&self, tokens: &mut TokenStream) {
220        let word = if *self { "true" } else { "false" };
221        tokens.append(Ident::new(word, Span::call_site()));
222    }
223}
224
225impl ToTokens for CStr {
226    fn to_tokens(&self, tokens: &mut TokenStream) {
227        tokens.append(Literal::c_string(self));
228    }
229}
230
231impl ToTokens for CString {
232    fn to_tokens(&self, tokens: &mut TokenStream) {
233        tokens.append(Literal::c_string(self));
234    }
235}
236
237impl ToTokens for Group {
238    fn to_tokens(&self, tokens: &mut TokenStream) {
239        tokens.append(self.clone());
240    }
241}
242
243impl ToTokens for Ident {
244    fn to_tokens(&self, tokens: &mut TokenStream) {
245        tokens.append(self.clone());
246    }
247}
248
249impl ToTokens for Punct {
250    fn to_tokens(&self, tokens: &mut TokenStream) {
251        tokens.append(self.clone());
252    }
253}
254
255impl ToTokens for Literal {
256    fn to_tokens(&self, tokens: &mut TokenStream) {
257        tokens.append(self.clone());
258    }
259}
260
261impl ToTokens for TokenTree {
262    fn to_tokens(&self, tokens: &mut TokenStream) {
263        tokens.append(self.clone());
264    }
265}
266
267impl ToTokens for TokenStream {
268    fn to_tokens(&self, tokens: &mut TokenStream) {
269        tokens.extend(iter::once(self.clone()));
270    }
271
272    fn into_token_stream(self) -> TokenStream {
273        self
274    }
275}