to_tokens.rs 6.8 KB

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