1use std::borrow::Cow;
2use std::rc::Rc;
3
4use super::{Literal, TokenStream};
5
6/// Types that can be interpolated inside a `quote!` invocation.
7///
8/// [`quote!`]: macro.quote.html
9pub 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
35impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
36 fn to_tokens(&self, tokens: &mut TokenStream) {
37 (**self).to_tokens(tokens);
38 }
39}
40
41impl<'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
47impl<'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
53impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
54 fn to_tokens(&self, tokens: &mut TokenStream) {
55 (**self).to_tokens(tokens);
56 }
57}
58
59impl<T: ?Sized + ToTokens> ToTokens for Rc<T> {
60 fn to_tokens(&self, tokens: &mut TokenStream) {
61 (**self).to_tokens(tokens);
62 }
63}
64
65impl<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
73impl 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
81impl ToTokens for String {
82 fn to_tokens(&self, tokens: &mut TokenStream) {
83 self.as_str().to_tokens(tokens);
84 }
85}
86
87macro_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
99primitive! {
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
118impl 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
127impl 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
135impl ToTokens for Literal {
136 fn to_tokens(&self, tokens: &mut TokenStream) {
137 tokens.push_str(self.as_str());
138 }
139}
140
141impl 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