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