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