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: &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(token: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(token:Literal::i8_suffixed(*self));
127 }
128}
129
130impl ToTokens for i16 {
131 fn to_tokens(&self, tokens: &mut TokenStream) {
132 tokens.append(token:Literal::i16_suffixed(*self));
133 }
134}
135
136impl ToTokens for i32 {
137 fn to_tokens(&self, tokens: &mut TokenStream) {
138 tokens.append(token:Literal::i32_suffixed(*self));
139 }
140}
141
142impl ToTokens for i64 {
143 fn to_tokens(&self, tokens: &mut TokenStream) {
144 tokens.append(token:Literal::i64_suffixed(*self));
145 }
146}
147
148impl ToTokens for i128 {
149 fn to_tokens(&self, tokens: &mut TokenStream) {
150 tokens.append(token:Literal::i128_suffixed(*self));
151 }
152}
153
154impl ToTokens for isize {
155 fn to_tokens(&self, tokens: &mut TokenStream) {
156 tokens.append(token:Literal::isize_suffixed(*self));
157 }
158}
159
160impl ToTokens for u8 {
161 fn to_tokens(&self, tokens: &mut TokenStream) {
162 tokens.append(token:Literal::u8_suffixed(*self));
163 }
164}
165
166impl ToTokens for u16 {
167 fn to_tokens(&self, tokens: &mut TokenStream) {
168 tokens.append(token:Literal::u16_suffixed(*self));
169 }
170}
171
172impl ToTokens for u32 {
173 fn to_tokens(&self, tokens: &mut TokenStream) {
174 tokens.append(token:Literal::u32_suffixed(*self));
175 }
176}
177
178impl ToTokens for u64 {
179 fn to_tokens(&self, tokens: &mut TokenStream) {
180 tokens.append(token:Literal::u64_suffixed(*self));
181 }
182}
183
184impl ToTokens for u128 {
185 fn to_tokens(&self, tokens: &mut TokenStream) {
186 tokens.append(token:Literal::u128_suffixed(*self));
187 }
188}
189
190impl ToTokens for usize {
191 fn to_tokens(&self, tokens: &mut TokenStream) {
192 tokens.append(token:Literal::usize_suffixed(*self));
193 }
194}
195
196impl ToTokens for f32 {
197 fn to_tokens(&self, tokens: &mut TokenStream) {
198 tokens.append(token:Literal::f32_suffixed(*self));
199 }
200}
201
202impl ToTokens for f64 {
203 fn to_tokens(&self, tokens: &mut TokenStream) {
204 tokens.append(token:Literal::f64_suffixed(*self));
205 }
206}
207
208impl ToTokens for char {
209 fn to_tokens(&self, tokens: &mut TokenStream) {
210 tokens.append(token:Literal::character(*self));
211 }
212}
213
214impl ToTokens for bool {
215 fn to_tokens(&self, tokens: &mut TokenStream) {
216 let word: &'static str = if *self { "true" } else { "false" };
217 tokens.append(token:Ident::new(string:word, Span::call_site()));
218 }
219}
220
221impl ToTokens for CStr {
222 fn to_tokens(&self, tokens: &mut TokenStream) {
223 tokens.append(token:Literal::c_string(self));
224 }
225}
226
227impl ToTokens for CString {
228 fn to_tokens(&self, tokens: &mut TokenStream) {
229 tokens.append(token: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:iter::once(self.clone()));
266 }
267
268 fn into_token_stream(self) -> TokenStream {
269 self
270 }
271}
272