| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- use super::TokenStreamExt;
- use alloc::borrow::Cow;
- use alloc::rc::Rc;
- use core::iter;
- use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
- use std::ffi::{CStr, CString};
- /// Types that can be interpolated inside a `quote!` invocation.
- 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`.
- ///
- /// # 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<T: ?Sized + ToTokens> ToTokens for &T {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- (**self).to_tokens(tokens);
- }
- }
- impl<T: ?Sized + ToTokens> ToTokens for &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(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);
- }
- }
- impl ToTokens for i8 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::i8_suffixed(*self));
- }
- }
- impl ToTokens for i16 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::i16_suffixed(*self));
- }
- }
- impl ToTokens for i32 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::i32_suffixed(*self));
- }
- }
- impl ToTokens for i64 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::i64_suffixed(*self));
- }
- }
- impl ToTokens for i128 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::i128_suffixed(*self));
- }
- }
- impl ToTokens for isize {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::isize_suffixed(*self));
- }
- }
- impl ToTokens for u8 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::u8_suffixed(*self));
- }
- }
- impl ToTokens for u16 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::u16_suffixed(*self));
- }
- }
- impl ToTokens for u32 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::u32_suffixed(*self));
- }
- }
- impl ToTokens for u64 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::u64_suffixed(*self));
- }
- }
- impl ToTokens for u128 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::u128_suffixed(*self));
- }
- }
- impl ToTokens for usize {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::usize_suffixed(*self));
- }
- }
- impl ToTokens for f32 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::f32_suffixed(*self));
- }
- }
- impl ToTokens for f64 {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::f64_suffixed(*self));
- }
- }
- 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 CStr {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::c_string(self));
- }
- }
- impl ToTokens for CString {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append(Literal::c_string(self));
- }
- }
- 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, tokens: &mut TokenStream) {
- tokens.append(self.clone());
- }
- }
- impl ToTokens for TokenStream {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.extend(iter::once(self.clone()));
- }
- fn into_token_stream(self) -> TokenStream {
- self
- }
- }
|