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 /// ```edition2018 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. into_token_stream(self) -> TokenStream where Self: Sized,61 fn into_token_stream(self) -> TokenStream 62 where 63 Self: Sized, 64 { 65 let mut tokens = TokenStream::new(); 66 self.to_tokens(&mut tokens); 67 tokens 68 } 69 } 70 71 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T { to_tokens(&self, tokens: &mut TokenStream)72 fn to_tokens(&self, tokens: &mut TokenStream) { 73 (**self).to_tokens(tokens); 74 } 75 } 76 77 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut 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 + ToOwned + ToTokens> ToTokens for Cow<'a, 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<T: ?Sized + ToTokens> ToTokens for Box<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 Rc<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: ToTokens> ToTokens for Option<T> { to_tokens(&self, tokens: &mut TokenStream)102 fn to_tokens(&self, tokens: &mut TokenStream) { 103 if let Some(ref t) = *self { 104 t.to_tokens(tokens); 105 } 106 } 107 } 108 109 impl ToTokens for str { to_tokens(&self, tokens: &mut TokenStream)110 fn to_tokens(&self, tokens: &mut TokenStream) { 111 tokens.append(Literal::string(self)); 112 } 113 } 114 115 impl ToTokens for String { to_tokens(&self, tokens: &mut TokenStream)116 fn to_tokens(&self, tokens: &mut TokenStream) { 117 self.as_str().to_tokens(tokens); 118 } 119 } 120 121 macro_rules! primitive { 122 ($($t:ident => $name:ident)*) => ($( 123 impl ToTokens for $t { 124 fn to_tokens(&self, tokens: &mut TokenStream) { 125 tokens.append(Literal::$name(*self)); 126 } 127 } 128 )*) 129 } 130 131 primitive! { 132 i8 => i8_suffixed 133 i16 => i16_suffixed 134 i32 => i32_suffixed 135 i64 => i64_suffixed 136 isize => isize_suffixed 137 138 u8 => u8_suffixed 139 u16 => u16_suffixed 140 u32 => u32_suffixed 141 u64 => u64_suffixed 142 usize => usize_suffixed 143 144 f32 => f32_suffixed 145 f64 => f64_suffixed 146 } 147 148 #[cfg(integer128)] 149 primitive! { 150 i128 => i128_suffixed 151 u128 => u128_suffixed 152 } 153 154 impl ToTokens for char { to_tokens(&self, tokens: &mut TokenStream)155 fn to_tokens(&self, tokens: &mut TokenStream) { 156 tokens.append(Literal::character(*self)); 157 } 158 } 159 160 impl ToTokens for bool { to_tokens(&self, tokens: &mut TokenStream)161 fn to_tokens(&self, tokens: &mut TokenStream) { 162 let word = if *self { "true" } else { "false" }; 163 tokens.append(Ident::new(word, Span::call_site())); 164 } 165 } 166 167 impl ToTokens for Group { to_tokens(&self, tokens: &mut TokenStream)168 fn to_tokens(&self, tokens: &mut TokenStream) { 169 tokens.append(self.clone()); 170 } 171 } 172 173 impl ToTokens for Ident { to_tokens(&self, tokens: &mut TokenStream)174 fn to_tokens(&self, tokens: &mut TokenStream) { 175 tokens.append(self.clone()); 176 } 177 } 178 179 impl ToTokens for Punct { to_tokens(&self, tokens: &mut TokenStream)180 fn to_tokens(&self, tokens: &mut TokenStream) { 181 tokens.append(self.clone()); 182 } 183 } 184 185 impl ToTokens for Literal { to_tokens(&self, tokens: &mut TokenStream)186 fn to_tokens(&self, tokens: &mut TokenStream) { 187 tokens.append(self.clone()); 188 } 189 } 190 191 impl ToTokens for TokenTree { to_tokens(&self, dst: &mut TokenStream)192 fn to_tokens(&self, dst: &mut TokenStream) { 193 dst.append(self.clone()); 194 } 195 } 196 197 impl ToTokens for TokenStream { to_tokens(&self, dst: &mut TokenStream)198 fn to_tokens(&self, dst: &mut TokenStream) { 199 dst.extend(iter::once(self.clone())); 200 } 201 into_token_stream(self) -> TokenStream202 fn into_token_stream(self) -> TokenStream { 203 self 204 } 205 } 206