• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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