standalone_quote/
to_tokens.rs

1use super::Tokens;
2
3use std::borrow::Cow;
4
5use proc_macro2::{Literal, Span, Term, TokenNode, TokenTree, TokenStream};
6
7fn tt(kind: TokenNode) -> TokenTree {
8    TokenTree {
9        span: Span::def_site(),
10        kind: kind,
11    }
12}
13
14/// Types that can be interpolated inside a [`quote!`] invocation.
15///
16/// [`quote!`]: macro.quote.html
17pub trait ToTokens {
18    /// Write `self` to the given `Tokens`.
19    ///
20    /// Example implementation for a struct representing Rust paths like
21    /// `std::cmp::PartialEq`:
22    ///
23    /// ```
24    /// extern crate quote;
25    /// use quote::{Tokens, ToTokens};
26    ///
27    /// extern crate proc_macro2;
28    /// use proc_macro2::{TokenTree, TokenNode, Spacing, Span};
29    ///
30    /// pub struct Path {
31    ///     pub global: bool,
32    ///     pub segments: Vec<PathSegment>,
33    /// }
34    ///
35    /// impl ToTokens for Path {
36    ///     fn to_tokens(&self, tokens: &mut Tokens) {
37    ///         for (i, segment) in self.segments.iter().enumerate() {
38    ///             if i > 0 || self.global {
39    ///                 // Double colon `::`
40    ///                 tokens.append(TokenTree {
41    ///                     span: Span::def_site(),
42    ///                     kind: TokenNode::Op(':', Spacing::Joint),
43    ///                 });
44    ///                 tokens.append(TokenTree {
45    ///                     span: Span::def_site(),
46    ///                     kind: TokenNode::Op(':', Spacing::Alone),
47    ///                 });
48    ///             }
49    ///             segment.to_tokens(tokens);
50    ///         }
51    ///     }
52    /// }
53    /// #
54    /// # pub struct PathSegment;
55    /// #
56    /// # impl ToTokens for PathSegment {
57    /// #     fn to_tokens(&self, tokens: &mut Tokens) {
58    /// #         unimplemented!()
59    /// #     }
60    /// # }
61    /// #
62    /// # fn main() {}
63    /// ```
64    fn to_tokens(&self, tokens: &mut Tokens);
65
66    /// Convert `self` directly into a `Tokens` object.
67    ///
68    /// This method is implicitly implemented using `to_tokens`, and acts as a
69    /// convenience method for consumers of the `ToTokens` trait.
70    fn into_tokens(self) -> Tokens
71    where
72        Self: Sized,
73    {
74        let mut tokens = Tokens::new();
75        self.to_tokens(&mut tokens);
76        tokens
77    }
78}
79
80impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
81    fn to_tokens(&self, tokens: &mut Tokens) {
82        (**self).to_tokens(tokens);
83    }
84}
85
86impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
87    fn to_tokens(&self, tokens: &mut Tokens) {
88        (**self).to_tokens(tokens);
89    }
90}
91
92impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
93    fn to_tokens(&self, tokens: &mut Tokens) {
94        (**self).to_tokens(tokens);
95    }
96}
97
98impl<T: ToTokens> ToTokens for Option<T> {
99    fn to_tokens(&self, tokens: &mut Tokens) {
100        if let Some(ref t) = *self {
101            t.to_tokens(tokens);
102        }
103    }
104}
105
106impl ToTokens for str {
107    fn to_tokens(&self, tokens: &mut Tokens) {
108        tokens.append(tt(TokenNode::Literal(Literal::string(self))));
109    }
110}
111
112impl ToTokens for String {
113    fn to_tokens(&self, tokens: &mut Tokens) {
114        self.as_str().to_tokens(tokens);
115    }
116}
117
118macro_rules! primitive {
119    ($($t:ident)*) => ($(
120        impl ToTokens for $t {
121            fn to_tokens(&self, tokens: &mut Tokens) {
122                tokens.append(tt(TokenNode::Literal(Literal::$t(*self))));
123            }
124        }
125    )*)
126}
127
128primitive! {
129    i8 i16 i32 i64 isize
130    u8 u16 u32 u64 usize
131    f32 f64
132}
133
134impl ToTokens for char {
135    fn to_tokens(&self, tokens: &mut Tokens) {
136        tokens.append(tt(TokenNode::Literal(Literal::character(*self))));
137    }
138}
139
140impl ToTokens for bool {
141    fn to_tokens(&self, tokens: &mut Tokens) {
142        let word = if *self { "true" } else { "false" };
143        tokens.append(tt(TokenNode::Term(Term::intern(word))));
144    }
145}
146
147impl ToTokens for Term {
148    fn to_tokens(&self, tokens: &mut Tokens) {
149        tokens.append(tt(TokenNode::Term(*self)));
150    }
151}
152
153impl ToTokens for Literal {
154    fn to_tokens(&self, tokens: &mut Tokens) {
155        tokens.append(tt(TokenNode::Literal(self.clone())));
156    }
157}
158
159impl ToTokens for TokenNode {
160    fn to_tokens(&self, tokens: &mut Tokens) {
161        tokens.append(tt(self.clone()));
162    }
163}
164
165impl ToTokens for TokenTree {
166    fn to_tokens(&self, dst: &mut Tokens) {
167        dst.append(self.clone());
168    }
169}
170
171impl ToTokens for TokenStream {
172    fn to_tokens(&self, dst: &mut Tokens) {
173        dst.append_all(self.clone().into_iter());
174    }
175}