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