]> git.proxmox.com Git - cargo.git/blob - vendor/quote/src/to_tokens.rs
New upstream version 0.33.0
[cargo.git] / vendor / quote / src / to_tokens.rs
1 use super::TokenStreamExt;
2
3 use std::borrow::Cow;
4 use std::iter;
5
6 use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
7
8 /// Types that can be interpolated inside a [`quote!`] invocation.
9 ///
10 /// [`quote!`]: macro.quote.html
11 pub trait ToTokens {
12 /// Write `self` to the given `TokenStream`.
13 ///
14 /// The token append methods provided by the [`TokenStreamExt`] extension
15 /// trait may be useful for implementing `ToTokens`.
16 ///
17 /// [`TokenStreamExt`]: trait.TokenStreamExt.html
18 ///
19 /// # Example
20 ///
21 /// Example implementation for a struct representing Rust paths like
22 /// `std::cmp::PartialEq`:
23 ///
24 /// ```edition2018
25 /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
26 /// use quote::{TokenStreamExt, ToTokens};
27 ///
28 /// pub struct Path {
29 /// pub global: bool,
30 /// pub segments: Vec<PathSegment>,
31 /// }
32 ///
33 /// impl ToTokens for Path {
34 /// fn to_tokens(&self, tokens: &mut TokenStream) {
35 /// for (i, segment) in self.segments.iter().enumerate() {
36 /// if i > 0 || self.global {
37 /// // Double colon `::`
38 /// tokens.append(Punct::new(':', Spacing::Joint));
39 /// tokens.append(Punct::new(':', Spacing::Alone));
40 /// }
41 /// segment.to_tokens(tokens);
42 /// }
43 /// }
44 /// }
45 /// #
46 /// # pub struct PathSegment;
47 /// #
48 /// # impl ToTokens for PathSegment {
49 /// # fn to_tokens(&self, tokens: &mut TokenStream) {
50 /// # unimplemented!()
51 /// # }
52 /// # }
53 /// ```
54 fn to_tokens(&self, tokens: &mut TokenStream);
55
56 /// Convert `self` directly into a `TokenStream` object.
57 ///
58 /// This method is implicitly implemented using `to_tokens`, and acts as a
59 /// convenience method for consumers of the `ToTokens` trait.
60 fn into_token_stream(self) -> TokenStream
61 where
62 Self: Sized,
63 {
64 let mut tokens = TokenStream::new();
65 self.to_tokens(&mut tokens);
66 tokens
67 }
68 }
69
70 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
71 fn to_tokens(&self, tokens: &mut TokenStream) {
72 (**self).to_tokens(tokens);
73 }
74 }
75
76 impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut T {
77 fn to_tokens(&self, tokens: &mut TokenStream) {
78 (**self).to_tokens(tokens);
79 }
80 }
81
82 impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
83 fn to_tokens(&self, tokens: &mut TokenStream) {
84 (**self).to_tokens(tokens);
85 }
86 }
87
88 impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
89 fn to_tokens(&self, tokens: &mut TokenStream) {
90 (**self).to_tokens(tokens);
91 }
92 }
93
94 impl<T: ToTokens> ToTokens for Option<T> {
95 fn to_tokens(&self, tokens: &mut TokenStream) {
96 if let Some(ref t) = *self {
97 t.to_tokens(tokens);
98 }
99 }
100 }
101
102 impl ToTokens for str {
103 fn to_tokens(&self, tokens: &mut TokenStream) {
104 tokens.append(Literal::string(self));
105 }
106 }
107
108 impl ToTokens for String {
109 fn to_tokens(&self, tokens: &mut TokenStream) {
110 self.as_str().to_tokens(tokens);
111 }
112 }
113
114 macro_rules! primitive {
115 ($($t:ident => $name:ident)*) => ($(
116 impl ToTokens for $t {
117 fn to_tokens(&self, tokens: &mut TokenStream) {
118 tokens.append(Literal::$name(*self));
119 }
120 }
121 )*)
122 }
123
124 primitive! {
125 i8 => i8_suffixed
126 i16 => i16_suffixed
127 i32 => i32_suffixed
128 i64 => i64_suffixed
129 isize => isize_suffixed
130
131 u8 => u8_suffixed
132 u16 => u16_suffixed
133 u32 => u32_suffixed
134 u64 => u64_suffixed
135 usize => usize_suffixed
136
137 f32 => f32_suffixed
138 f64 => f64_suffixed
139 }
140
141 #[cfg(integer128)]
142 primitive! {
143 i128 => i128_suffixed
144 u128 => u128_suffixed
145 }
146
147 impl ToTokens for char {
148 fn to_tokens(&self, tokens: &mut TokenStream) {
149 tokens.append(Literal::character(*self));
150 }
151 }
152
153 impl ToTokens for bool {
154 fn to_tokens(&self, tokens: &mut TokenStream) {
155 let word = if *self { "true" } else { "false" };
156 tokens.append(Ident::new(word, Span::call_site()));
157 }
158 }
159
160 impl ToTokens for Group {
161 fn to_tokens(&self, tokens: &mut TokenStream) {
162 tokens.append(self.clone());
163 }
164 }
165
166 impl ToTokens for Ident {
167 fn to_tokens(&self, tokens: &mut TokenStream) {
168 tokens.append(self.clone());
169 }
170 }
171
172 impl ToTokens for Punct {
173 fn to_tokens(&self, tokens: &mut TokenStream) {
174 tokens.append(self.clone());
175 }
176 }
177
178 impl ToTokens for Literal {
179 fn to_tokens(&self, tokens: &mut TokenStream) {
180 tokens.append(self.clone());
181 }
182 }
183
184 impl ToTokens for TokenTree {
185 fn to_tokens(&self, dst: &mut TokenStream) {
186 dst.append(self.clone());
187 }
188 }
189
190 impl ToTokens for TokenStream {
191 fn to_tokens(&self, dst: &mut TokenStream) {
192 dst.extend(iter::once(self.clone()));
193 }
194
195 fn into_token_stream(self) -> TokenStream {
196 self
197 }
198 }