use std::borrow::Cow; use std::ffi::{CStr, CString}; use std::rc::Rc; use crate::{ConcatTreesHelper, Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; /// Types that can be interpolated inside a [`quote!`] invocation. /// /// [`quote!`]: crate::quote! #[unstable(feature = "proc_macro_totokens", issue = "130977")] pub trait ToTokens { /// Write `self` to the given `TokenStream`. /// /// # Example /// /// Example implementation for a struct representing Rust paths like /// `std::cmp::PartialEq`: /// /// ``` /// #![feature(proc_macro_totokens)] /// /// use std::iter; /// use proc_macro::{Spacing, Punct, TokenStream, TokenTree, ToTokens}; /// /// pub struct Path { /// pub global: bool, /// pub segments: Vec, /// } /// /// 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.extend(iter::once(TokenTree::from(Punct::new(':', Spacing::Joint)))); /// tokens.extend(iter::once(TokenTree::from(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() } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for TokenTree { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend_one(self.clone()); } fn into_token_stream(self) -> TokenStream { let mut builder = ConcatTreesHelper::new(1); builder.push(self); builder.build() } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for TokenStream { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend(self.clone()); } fn into_token_stream(self) -> TokenStream { self } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Literal { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend_one(TokenTree::from(self.clone())); } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Ident { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend_one(TokenTree::from(self.clone())); } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Punct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend_one(TokenTree::from(self.clone())); } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Group { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend_one(TokenTree::from(self.clone())); } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for &T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for &mut T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Box { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Rc { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Cow<'_, T> { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for Option { fn to_tokens(&self, tokens: &mut TokenStream) { if let Some(t) = self { t.to_tokens(tokens); } } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for u8 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::u8_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for u16 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::u16_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for u32 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::u32_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for u64 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::u64_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for u128 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::u128_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for i8 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::i8_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for i16 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::i16_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for i32 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::i32_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for i64 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::i64_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for i128 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::i128_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for f32 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::f32_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for f64 { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::f64_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for usize { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::usize_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for isize { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::isize_suffixed(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for bool { fn to_tokens(&self, tokens: &mut TokenStream) { let word = if *self { "true" } else { "false" }; Ident::new(word, Span::call_site()).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for char { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::character(*self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for str { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::string(self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for String { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::string(self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for CStr { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::c_string(self).to_tokens(tokens) } } #[unstable(feature = "proc_macro_totokens", issue = "130977")] impl ToTokens for CString { fn to_tokens(&self, tokens: &mut TokenStream) { Literal::c_string(self).to_tokens(tokens) } }