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