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