1 | use std::borrow::Cow; |
2 | use std::rc::Rc; |
3 | |
4 | use super::{Literal, TokenStream}; |
5 | |
6 | /// Types that can be interpolated inside a `quote!` invocation. |
7 | /// |
8 | /// [`quote!`]: macro.quote.html |
9 | pub trait ToTokens { |
10 | /// Write `self` to the given `TokenStream`. |
11 | fn to_tokens(&self, tokens: &mut TokenStream); |
12 | |
13 | /// Convert `self` directly into a `TokenStream` object. |
14 | /// |
15 | /// This method is implicitly implemented using `to_tokens`, and acts as a |
16 | /// convenience method for consumers of the `ToTokens` trait. |
17 | fn to_token_stream(&self) -> TokenStream { |
18 | let mut tokens = TokenStream::new(); |
19 | self.to_tokens(&mut tokens); |
20 | tokens |
21 | } |
22 | |
23 | /// Convert `self` directly into a `TokenStream` object. |
24 | /// |
25 | /// This method is implicitly implemented using `to_tokens`, and acts as a |
26 | /// convenience method for consumers of the `ToTokens` trait. |
27 | fn into_token_stream(self) -> TokenStream |
28 | where |
29 | Self: Sized, |
30 | { |
31 | self.to_token_stream() |
32 | } |
33 | } |
34 | |
35 | impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T { |
36 | fn to_tokens(&self, tokens: &mut TokenStream) { |
37 | (**self).to_tokens(tokens); |
38 | } |
39 | } |
40 | |
41 | impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut T { |
42 | fn to_tokens(&self, tokens: &mut TokenStream) { |
43 | (**self).to_tokens(tokens); |
44 | } |
45 | } |
46 | |
47 | impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> { |
48 | fn to_tokens(&self, tokens: &mut TokenStream) { |
49 | (**self).to_tokens(tokens); |
50 | } |
51 | } |
52 | |
53 | impl<T: ?Sized + ToTokens> ToTokens for Box<T> { |
54 | fn to_tokens(&self, tokens: &mut TokenStream) { |
55 | (**self).to_tokens(tokens); |
56 | } |
57 | } |
58 | |
59 | impl<T: ?Sized + ToTokens> ToTokens for Rc<T> { |
60 | fn to_tokens(&self, tokens: &mut TokenStream) { |
61 | (**self).to_tokens(tokens); |
62 | } |
63 | } |
64 | |
65 | impl<T: ToTokens> ToTokens for Option<T> { |
66 | fn to_tokens(&self, tokens: &mut TokenStream) { |
67 | if let Some(ref t: &T) = *self { |
68 | t.to_tokens(tokens); |
69 | } |
70 | } |
71 | } |
72 | |
73 | impl ToTokens for str { |
74 | fn to_tokens(&self, tokens: &mut TokenStream) { |
75 | tokens.push_str(" \"" ); |
76 | tokens.push_str(self); |
77 | tokens.push('"' ); |
78 | } |
79 | } |
80 | |
81 | impl ToTokens for String { |
82 | fn to_tokens(&self, tokens: &mut TokenStream) { |
83 | self.as_str().to_tokens(tokens); |
84 | } |
85 | } |
86 | |
87 | macro_rules! primitive { |
88 | ($($t:ident => $name:ident)*) => ($( |
89 | impl ToTokens for $t { |
90 | fn to_tokens(&self, tokens: &mut TokenStream) { |
91 | tokens.push_space(); |
92 | tokens.push_str(&self.to_string()); |
93 | tokens.push_str(stringify!($t)); |
94 | } |
95 | } |
96 | )*) |
97 | } |
98 | |
99 | primitive! { |
100 | i8 => i8_suffixed |
101 | i16 => i16_suffixed |
102 | i32 => i32_suffixed |
103 | i64 => i64_suffixed |
104 | i128 => i128_suffixed |
105 | isize => isize_suffixed |
106 | |
107 | u8 => u8_suffixed |
108 | u16 => u16_suffixed |
109 | u32 => u32_suffixed |
110 | u64 => u64_suffixed |
111 | u128 => u128_suffixed |
112 | usize => usize_suffixed |
113 | |
114 | f32 => f32_suffixed |
115 | f64 => f64_suffixed |
116 | } |
117 | |
118 | impl ToTokens for char { |
119 | fn to_tokens(&self, tokens: &mut TokenStream) { |
120 | tokens.push_space(); |
121 | tokens.push(' \'' ); |
122 | tokens.push(*self); |
123 | tokens.push(' \'' ); |
124 | } |
125 | } |
126 | |
127 | impl ToTokens for bool { |
128 | fn to_tokens(&self, tokens: &mut TokenStream) { |
129 | let word: &str = if *self { "true" } else { "false" }; |
130 | tokens.push_space(); |
131 | tokens.push_str(word); |
132 | } |
133 | } |
134 | |
135 | impl ToTokens for Literal { |
136 | fn to_tokens(&self, tokens: &mut TokenStream) { |
137 | tokens.push_str(self.as_str()); |
138 | } |
139 | } |
140 | |
141 | impl ToTokens for TokenStream { |
142 | fn to_tokens(&self, dst: &mut TokenStream) { |
143 | dst.combine(self); |
144 | } |
145 | |
146 | fn into_token_stream(self) -> TokenStream { |
147 | self |
148 | } |
149 | } |
150 | |