proc_macro/
to_tokens.rs

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