• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::TokenStreamExt;
2 use alloc::borrow::Cow;
3 use alloc::rc::Rc;
4 use core::iter;
5 use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
6 use std::ffi::{CStr, CString};
7 
8 /// Types that can be interpolated inside a `quote!` invocation.
9 ///
10 /// [`quote!`]: macro.quote.html
11 pub 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     /// ```
to_tokens(&self, tokens: &mut TokenStream)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.
to_token_stream(&self) -> TokenStream60     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.
into_token_stream(self) -> TokenStream where Self: Sized,70     fn into_token_stream(self) -> TokenStream
71     where
72         Self: Sized,
73     {
74         self.to_token_stream()
75     }
76 }
77 
78 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
to_tokens(&self, tokens: &mut TokenStream)79     fn to_tokens(&self, tokens: &mut TokenStream) {
80         (**self).to_tokens(tokens);
81     }
82 }
83 
84 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut T {
to_tokens(&self, tokens: &mut TokenStream)85     fn to_tokens(&self, tokens: &mut TokenStream) {
86         (**self).to_tokens(tokens);
87     }
88 }
89 
90 impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
to_tokens(&self, tokens: &mut TokenStream)91     fn to_tokens(&self, tokens: &mut TokenStream) {
92         (**self).to_tokens(tokens);
93     }
94 }
95 
96 impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
to_tokens(&self, tokens: &mut TokenStream)97     fn to_tokens(&self, tokens: &mut TokenStream) {
98         (**self).to_tokens(tokens);
99     }
100 }
101 
102 impl<T: ?Sized + ToTokens> ToTokens for Rc<T> {
to_tokens(&self, tokens: &mut TokenStream)103     fn to_tokens(&self, tokens: &mut TokenStream) {
104         (**self).to_tokens(tokens);
105     }
106 }
107 
108 impl<T: ToTokens> ToTokens for Option<T> {
to_tokens(&self, tokens: &mut TokenStream)109     fn to_tokens(&self, tokens: &mut TokenStream) {
110         if let Some(t) = self {
111             t.to_tokens(tokens);
112         }
113     }
114 }
115 
116 impl ToTokens for str {
to_tokens(&self, tokens: &mut TokenStream)117     fn to_tokens(&self, tokens: &mut TokenStream) {
118         tokens.append(Literal::string(self));
119     }
120 }
121 
122 impl ToTokens for String {
to_tokens(&self, tokens: &mut TokenStream)123     fn to_tokens(&self, tokens: &mut TokenStream) {
124         self.as_str().to_tokens(tokens);
125     }
126 }
127 
128 impl ToTokens for i8 {
to_tokens(&self, tokens: &mut TokenStream)129     fn to_tokens(&self, tokens: &mut TokenStream) {
130         tokens.append(Literal::i8_suffixed(*self));
131     }
132 }
133 
134 impl ToTokens for i16 {
to_tokens(&self, tokens: &mut TokenStream)135     fn to_tokens(&self, tokens: &mut TokenStream) {
136         tokens.append(Literal::i16_suffixed(*self));
137     }
138 }
139 
140 impl ToTokens for i32 {
to_tokens(&self, tokens: &mut TokenStream)141     fn to_tokens(&self, tokens: &mut TokenStream) {
142         tokens.append(Literal::i32_suffixed(*self));
143     }
144 }
145 
146 impl ToTokens for i64 {
to_tokens(&self, tokens: &mut TokenStream)147     fn to_tokens(&self, tokens: &mut TokenStream) {
148         tokens.append(Literal::i64_suffixed(*self));
149     }
150 }
151 
152 impl ToTokens for i128 {
to_tokens(&self, tokens: &mut TokenStream)153     fn to_tokens(&self, tokens: &mut TokenStream) {
154         tokens.append(Literal::i128_suffixed(*self));
155     }
156 }
157 
158 impl ToTokens for isize {
to_tokens(&self, tokens: &mut TokenStream)159     fn to_tokens(&self, tokens: &mut TokenStream) {
160         tokens.append(Literal::isize_suffixed(*self));
161     }
162 }
163 
164 impl ToTokens for u8 {
to_tokens(&self, tokens: &mut TokenStream)165     fn to_tokens(&self, tokens: &mut TokenStream) {
166         tokens.append(Literal::u8_suffixed(*self));
167     }
168 }
169 
170 impl ToTokens for u16 {
to_tokens(&self, tokens: &mut TokenStream)171     fn to_tokens(&self, tokens: &mut TokenStream) {
172         tokens.append(Literal::u16_suffixed(*self));
173     }
174 }
175 
176 impl ToTokens for u32 {
to_tokens(&self, tokens: &mut TokenStream)177     fn to_tokens(&self, tokens: &mut TokenStream) {
178         tokens.append(Literal::u32_suffixed(*self));
179     }
180 }
181 
182 impl ToTokens for u64 {
to_tokens(&self, tokens: &mut TokenStream)183     fn to_tokens(&self, tokens: &mut TokenStream) {
184         tokens.append(Literal::u64_suffixed(*self));
185     }
186 }
187 
188 impl ToTokens for u128 {
to_tokens(&self, tokens: &mut TokenStream)189     fn to_tokens(&self, tokens: &mut TokenStream) {
190         tokens.append(Literal::u128_suffixed(*self));
191     }
192 }
193 
194 impl ToTokens for usize {
to_tokens(&self, tokens: &mut TokenStream)195     fn to_tokens(&self, tokens: &mut TokenStream) {
196         tokens.append(Literal::usize_suffixed(*self));
197     }
198 }
199 
200 impl ToTokens for f32 {
to_tokens(&self, tokens: &mut TokenStream)201     fn to_tokens(&self, tokens: &mut TokenStream) {
202         tokens.append(Literal::f32_suffixed(*self));
203     }
204 }
205 
206 impl ToTokens for f64 {
to_tokens(&self, tokens: &mut TokenStream)207     fn to_tokens(&self, tokens: &mut TokenStream) {
208         tokens.append(Literal::f64_suffixed(*self));
209     }
210 }
211 
212 impl ToTokens for char {
to_tokens(&self, tokens: &mut TokenStream)213     fn to_tokens(&self, tokens: &mut TokenStream) {
214         tokens.append(Literal::character(*self));
215     }
216 }
217 
218 impl ToTokens for bool {
to_tokens(&self, tokens: &mut TokenStream)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 
225 impl ToTokens for CStr {
to_tokens(&self, tokens: &mut TokenStream)226     fn to_tokens(&self, tokens: &mut TokenStream) {
227         tokens.append(Literal::c_string(self));
228     }
229 }
230 
231 impl ToTokens for CString {
to_tokens(&self, tokens: &mut TokenStream)232     fn to_tokens(&self, tokens: &mut TokenStream) {
233         tokens.append(Literal::c_string(self));
234     }
235 }
236 
237 impl ToTokens for Group {
to_tokens(&self, tokens: &mut TokenStream)238     fn to_tokens(&self, tokens: &mut TokenStream) {
239         tokens.append(self.clone());
240     }
241 }
242 
243 impl ToTokens for Ident {
to_tokens(&self, tokens: &mut TokenStream)244     fn to_tokens(&self, tokens: &mut TokenStream) {
245         tokens.append(self.clone());
246     }
247 }
248 
249 impl ToTokens for Punct {
to_tokens(&self, tokens: &mut TokenStream)250     fn to_tokens(&self, tokens: &mut TokenStream) {
251         tokens.append(self.clone());
252     }
253 }
254 
255 impl ToTokens for Literal {
to_tokens(&self, tokens: &mut TokenStream)256     fn to_tokens(&self, tokens: &mut TokenStream) {
257         tokens.append(self.clone());
258     }
259 }
260 
261 impl ToTokens for TokenTree {
to_tokens(&self, tokens: &mut TokenStream)262     fn to_tokens(&self, tokens: &mut TokenStream) {
263         tokens.append(self.clone());
264     }
265 }
266 
267 impl ToTokens for TokenStream {
to_tokens(&self, tokens: &mut TokenStream)268     fn to_tokens(&self, tokens: &mut TokenStream) {
269         tokens.extend(iter::once(self.clone()));
270     }
271 
into_token_stream(self) -> TokenStream272     fn into_token_stream(self) -> TokenStream {
273         self
274     }
275 }
276