• 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         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