1 | use super::TokenStreamExt; |
2 | use core::iter; |
3 | use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; |
4 | use std::borrow::Cow; |
5 | use std::rc::Rc; |
6 | |
7 | /// Types that can be interpolated inside a `quote!` invocation. |
8 | /// |
9 | /// [`quote!`]: macro.quote.html |
10 | pub 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 | |
77 | impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T { |
78 | fn to_tokens(&self, tokens: &mut TokenStream) { |
79 | (**self).to_tokens(tokens); |
80 | } |
81 | } |
82 | |
83 | impl<'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 | |
89 | impl<'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 | |
95 | impl<T: ?Sized + ToTokens> ToTokens for Box<T> { |
96 | fn to_tokens(&self, tokens: &mut TokenStream) { |
97 | (**self).to_tokens(tokens); |
98 | } |
99 | } |
100 | |
101 | impl<T: ?Sized + ToTokens> ToTokens for Rc<T> { |
102 | fn to_tokens(&self, tokens: &mut TokenStream) { |
103 | (**self).to_tokens(tokens); |
104 | } |
105 | } |
106 | |
107 | impl<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 | |
115 | impl ToTokens for str { |
116 | fn to_tokens(&self, tokens: &mut TokenStream) { |
117 | tokens.append(token:Literal::string(self)); |
118 | } |
119 | } |
120 | |
121 | impl ToTokens for String { |
122 | fn to_tokens(&self, tokens: &mut TokenStream) { |
123 | self.as_str().to_tokens(tokens); |
124 | } |
125 | } |
126 | |
127 | macro_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 | |
139 | primitive! { |
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 | |
158 | impl ToTokens for char { |
159 | fn to_tokens(&self, tokens: &mut TokenStream) { |
160 | tokens.append(token:Literal::character(*self)); |
161 | } |
162 | } |
163 | |
164 | impl 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 | |
171 | impl ToTokens for Group { |
172 | fn to_tokens(&self, tokens: &mut TokenStream) { |
173 | tokens.append(self.clone()); |
174 | } |
175 | } |
176 | |
177 | impl ToTokens for Ident { |
178 | fn to_tokens(&self, tokens: &mut TokenStream) { |
179 | tokens.append(self.clone()); |
180 | } |
181 | } |
182 | |
183 | impl ToTokens for Punct { |
184 | fn to_tokens(&self, tokens: &mut TokenStream) { |
185 | tokens.append(self.clone()); |
186 | } |
187 | } |
188 | |
189 | impl ToTokens for Literal { |
190 | fn to_tokens(&self, tokens: &mut TokenStream) { |
191 | tokens.append(self.clone()); |
192 | } |
193 | } |
194 | |
195 | impl ToTokens for TokenTree { |
196 | fn to_tokens(&self, dst: &mut TokenStream) { |
197 | dst.append(self.clone()); |
198 | } |
199 | } |
200 | |
201 | impl 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 | |