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 /// ``` to_tokens(&self, tokens: &mut TokenStream)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. to_token_stream(&self) -> TokenStream59 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. into_token_stream(self) -> TokenStream where Self: Sized,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 { to_tokens(&self, tokens: &mut TokenStream)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 { to_tokens(&self, tokens: &mut TokenStream)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> { to_tokens(&self, tokens: &mut TokenStream)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> { to_tokens(&self, tokens: &mut TokenStream)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> { to_tokens(&self, tokens: &mut TokenStream)102 fn to_tokens(&self, tokens: &mut TokenStream) { 103 (**self).to_tokens(tokens); 104 } 105 } 106 107 impl<T: ToTokens> ToTokens for Option<T> { to_tokens(&self, tokens: &mut TokenStream)108 fn to_tokens(&self, tokens: &mut TokenStream) { 109 if let Some(ref t) = *self { 110 t.to_tokens(tokens); 111 } 112 } 113 } 114 115 impl ToTokens for str { to_tokens(&self, tokens: &mut TokenStream)116 fn to_tokens(&self, tokens: &mut TokenStream) { 117 tokens.append(Literal::string(self)); 118 } 119 } 120 121 impl ToTokens for String { to_tokens(&self, tokens: &mut TokenStream)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 { 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