1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use super::TokenStreamExt; 4 use alloc::borrow::Cow; 5 use alloc::rc::Rc; 6 use core::iter; 7 use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; 8 use std::ffi::{CStr, CString}; 9 10 /// Types that can be interpolated inside a `quote!` invocation. 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 /// # Example 18 /// 19 /// Example implementation for a struct representing Rust paths like 20 /// `std::cmp::PartialEq`: 21 /// 22 /// ``` 23 /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream}; 24 /// use quote::{TokenStreamExt, ToTokens}; 25 /// 26 /// pub struct Path { 27 /// pub global: bool, 28 /// pub segments: Vec<PathSegment>, 29 /// } 30 /// 31 /// impl ToTokens for Path { 32 /// fn to_tokens(&self, tokens: &mut TokenStream) { 33 /// for (i, segment) in self.segments.iter().enumerate() { 34 /// if i > 0 || self.global { 35 /// // Double colon `::` 36 /// tokens.append(Punct::new(':', Spacing::Joint)); 37 /// tokens.append(Punct::new(':', Spacing::Alone)); 38 /// } 39 /// segment.to_tokens(tokens); 40 /// } 41 /// } 42 /// } 43 /// # 44 /// # pub struct PathSegment; 45 /// # 46 /// # impl ToTokens for PathSegment { 47 /// # fn to_tokens(&self, tokens: &mut TokenStream) { 48 /// # unimplemented!() 49 /// # } 50 /// # } 51 /// ``` to_tokens(&self, tokens: &mut TokenStream)52 fn to_tokens(&self, tokens: &mut TokenStream); 53 54 /// Convert `self` directly into a `TokenStream` object. 55 /// 56 /// This method is implicitly implemented using `to_tokens`, and acts as a 57 /// convenience method for consumers of the `ToTokens` trait. to_token_stream(&self) -> TokenStream58 fn to_token_stream(&self) -> TokenStream { 59 let mut tokens = TokenStream::new(); 60 self.to_tokens(&mut tokens); 61 tokens 62 } 63 64 /// Convert `self` directly into a `TokenStream` object. 65 /// 66 /// This method is implicitly implemented using `to_tokens`, and acts as a 67 /// convenience method for consumers of the `ToTokens` trait. into_token_stream(self) -> TokenStream where Self: Sized,68 fn into_token_stream(self) -> TokenStream 69 where 70 Self: Sized, 71 { 72 self.to_token_stream() 73 } 74 } 75 76 impl<T: ?Sized + ToTokens> ToTokens for &T { to_tokens(&self, tokens: &mut TokenStream)77 fn to_tokens(&self, tokens: &mut TokenStream) { 78 (**self).to_tokens(tokens); 79 } 80 } 81 82 impl<T: ?Sized + ToTokens> ToTokens for &mut T { to_tokens(&self, tokens: &mut TokenStream)83 fn to_tokens(&self, tokens: &mut TokenStream) { 84 (**self).to_tokens(tokens); 85 } 86 } 87 88 impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> { to_tokens(&self, tokens: &mut TokenStream)89 fn to_tokens(&self, tokens: &mut TokenStream) { 90 (**self).to_tokens(tokens); 91 } 92 } 93 94 impl<T: ?Sized + ToTokens> ToTokens for Box<T> { to_tokens(&self, tokens: &mut TokenStream)95 fn to_tokens(&self, tokens: &mut TokenStream) { 96 (**self).to_tokens(tokens); 97 } 98 } 99 100 impl<T: ?Sized + ToTokens> ToTokens for Rc<T> { to_tokens(&self, tokens: &mut TokenStream)101 fn to_tokens(&self, tokens: &mut TokenStream) { 102 (**self).to_tokens(tokens); 103 } 104 } 105 106 impl<T: ToTokens> ToTokens for Option<T> { to_tokens(&self, tokens: &mut TokenStream)107 fn to_tokens(&self, tokens: &mut TokenStream) { 108 if let Some(t) = self { 109 t.to_tokens(tokens); 110 } 111 } 112 } 113 114 impl ToTokens for str { to_tokens(&self, tokens: &mut TokenStream)115 fn to_tokens(&self, tokens: &mut TokenStream) { 116 tokens.append(Literal::string(self)); 117 } 118 } 119 120 impl ToTokens for String { to_tokens(&self, tokens: &mut TokenStream)121 fn to_tokens(&self, tokens: &mut TokenStream) { 122 self.as_str().to_tokens(tokens); 123 } 124 } 125 126 impl ToTokens for i8 { to_tokens(&self, tokens: &mut TokenStream)127 fn to_tokens(&self, tokens: &mut TokenStream) { 128 tokens.append(Literal::i8_suffixed(*self)); 129 } 130 } 131 132 impl ToTokens for i16 { to_tokens(&self, tokens: &mut TokenStream)133 fn to_tokens(&self, tokens: &mut TokenStream) { 134 tokens.append(Literal::i16_suffixed(*self)); 135 } 136 } 137 138 impl ToTokens for i32 { to_tokens(&self, tokens: &mut TokenStream)139 fn to_tokens(&self, tokens: &mut TokenStream) { 140 tokens.append(Literal::i32_suffixed(*self)); 141 } 142 } 143 144 impl ToTokens for i64 { to_tokens(&self, tokens: &mut TokenStream)145 fn to_tokens(&self, tokens: &mut TokenStream) { 146 tokens.append(Literal::i64_suffixed(*self)); 147 } 148 } 149 150 impl ToTokens for i128 { to_tokens(&self, tokens: &mut TokenStream)151 fn to_tokens(&self, tokens: &mut TokenStream) { 152 tokens.append(Literal::i128_suffixed(*self)); 153 } 154 } 155 156 impl ToTokens for isize { to_tokens(&self, tokens: &mut TokenStream)157 fn to_tokens(&self, tokens: &mut TokenStream) { 158 tokens.append(Literal::isize_suffixed(*self)); 159 } 160 } 161 162 impl ToTokens for u8 { to_tokens(&self, tokens: &mut TokenStream)163 fn to_tokens(&self, tokens: &mut TokenStream) { 164 tokens.append(Literal::u8_suffixed(*self)); 165 } 166 } 167 168 impl ToTokens for u16 { to_tokens(&self, tokens: &mut TokenStream)169 fn to_tokens(&self, tokens: &mut TokenStream) { 170 tokens.append(Literal::u16_suffixed(*self)); 171 } 172 } 173 174 impl ToTokens for u32 { to_tokens(&self, tokens: &mut TokenStream)175 fn to_tokens(&self, tokens: &mut TokenStream) { 176 tokens.append(Literal::u32_suffixed(*self)); 177 } 178 } 179 180 impl ToTokens for u64 { to_tokens(&self, tokens: &mut TokenStream)181 fn to_tokens(&self, tokens: &mut TokenStream) { 182 tokens.append(Literal::u64_suffixed(*self)); 183 } 184 } 185 186 impl ToTokens for u128 { to_tokens(&self, tokens: &mut TokenStream)187 fn to_tokens(&self, tokens: &mut TokenStream) { 188 tokens.append(Literal::u128_suffixed(*self)); 189 } 190 } 191 192 impl ToTokens for usize { to_tokens(&self, tokens: &mut TokenStream)193 fn to_tokens(&self, tokens: &mut TokenStream) { 194 tokens.append(Literal::usize_suffixed(*self)); 195 } 196 } 197 198 impl ToTokens for f32 { to_tokens(&self, tokens: &mut TokenStream)199 fn to_tokens(&self, tokens: &mut TokenStream) { 200 tokens.append(Literal::f32_suffixed(*self)); 201 } 202 } 203 204 impl ToTokens for f64 { to_tokens(&self, tokens: &mut TokenStream)205 fn to_tokens(&self, tokens: &mut TokenStream) { 206 tokens.append(Literal::f64_suffixed(*self)); 207 } 208 } 209 210 impl ToTokens for char { to_tokens(&self, tokens: &mut TokenStream)211 fn to_tokens(&self, tokens: &mut TokenStream) { 212 tokens.append(Literal::character(*self)); 213 } 214 } 215 216 impl ToTokens for bool { to_tokens(&self, tokens: &mut TokenStream)217 fn to_tokens(&self, tokens: &mut TokenStream) { 218 let word = if *self { "true" } else { "false" }; 219 tokens.append(Ident::new(word, Span::call_site())); 220 } 221 } 222 223 impl ToTokens for CStr { to_tokens(&self, tokens: &mut TokenStream)224 fn to_tokens(&self, tokens: &mut TokenStream) { 225 tokens.append(Literal::c_string(self)); 226 } 227 } 228 229 impl ToTokens for CString { to_tokens(&self, tokens: &mut TokenStream)230 fn to_tokens(&self, tokens: &mut TokenStream) { 231 tokens.append(Literal::c_string(self)); 232 } 233 } 234 235 impl ToTokens for Group { to_tokens(&self, tokens: &mut TokenStream)236 fn to_tokens(&self, tokens: &mut TokenStream) { 237 tokens.append(self.clone()); 238 } 239 } 240 241 impl ToTokens for Ident { to_tokens(&self, tokens: &mut TokenStream)242 fn to_tokens(&self, tokens: &mut TokenStream) { 243 tokens.append(self.clone()); 244 } 245 } 246 247 impl ToTokens for Punct { to_tokens(&self, tokens: &mut TokenStream)248 fn to_tokens(&self, tokens: &mut TokenStream) { 249 tokens.append(self.clone()); 250 } 251 } 252 253 impl ToTokens for Literal { to_tokens(&self, tokens: &mut TokenStream)254 fn to_tokens(&self, tokens: &mut TokenStream) { 255 tokens.append(self.clone()); 256 } 257 } 258 259 impl ToTokens for TokenTree { to_tokens(&self, tokens: &mut TokenStream)260 fn to_tokens(&self, tokens: &mut TokenStream) { 261 tokens.append(self.clone()); 262 } 263 } 264 265 impl ToTokens for TokenStream { to_tokens(&self, tokens: &mut TokenStream)266 fn to_tokens(&self, tokens: &mut TokenStream) { 267 tokens.extend(iter::once(self.clone())); 268 } 269 into_token_stream(self) -> TokenStream270 fn into_token_stream(self) -> TokenStream { 271 self 272 } 273 } 274