• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         $(
132             impl ToTokens for $t {
133                 fn to_tokens(&self, tokens: &mut TokenStream) {
134                     tokens.append(Literal::$name(*self));
135                 }
136             }
137         )*
138     };
139 }
140 
141 primitive! {
142     i8 => i8_suffixed
143     i16 => i16_suffixed
144     i32 => i32_suffixed
145     i64 => i64_suffixed
146     i128 => i128_suffixed
147     isize => isize_suffixed
148 
149     u8 => u8_suffixed
150     u16 => u16_suffixed
151     u32 => u32_suffixed
152     u64 => u64_suffixed
153     u128 => u128_suffixed
154     usize => usize_suffixed
155 
156     f32 => f32_suffixed
157     f64 => f64_suffixed
158 }
159 
160 impl ToTokens for char {
to_tokens(&self, tokens: &mut TokenStream)161     fn to_tokens(&self, tokens: &mut TokenStream) {
162         tokens.append(Literal::character(*self));
163     }
164 }
165 
166 impl ToTokens for bool {
to_tokens(&self, tokens: &mut TokenStream)167     fn to_tokens(&self, tokens: &mut TokenStream) {
168         let word = if *self { "true" } else { "false" };
169         tokens.append(Ident::new(word, Span::call_site()));
170     }
171 }
172 
173 impl ToTokens for Group {
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 Ident {
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 Punct {
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 Literal {
to_tokens(&self, tokens: &mut TokenStream)192     fn to_tokens(&self, tokens: &mut TokenStream) {
193         tokens.append(self.clone());
194     }
195 }
196 
197 impl ToTokens for TokenTree {
to_tokens(&self, dst: &mut TokenStream)198     fn to_tokens(&self, dst: &mut TokenStream) {
199         dst.append(self.clone());
200     }
201 }
202 
203 impl ToTokens for TokenStream {
to_tokens(&self, dst: &mut TokenStream)204     fn to_tokens(&self, dst: &mut TokenStream) {
205         dst.extend(iter::once(self.clone()));
206     }
207 
into_token_stream(self) -> TokenStream208     fn into_token_stream(self) -> TokenStream {
209         self
210     }
211 }
212