time_macros/to_tokens.rs
1use std::num::NonZero;
2
3use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
4
5/// Turn a type into a [`TokenStream`].
6pub(crate) trait ToTokenStream: Sized {
7 fn into_token_stream(self) -> TokenStream;
8}
9
10pub(crate) trait ToTokenTree: Sized {
11 fn into_token_tree(self) -> TokenTree;
12}
13
14impl<T: ToTokenTree> ToTokenStream for T {
15 fn into_token_stream(self) -> TokenStream {
16 self.into_token_tree().into()
17 }
18}
19
20impl ToTokenTree for bool {
21 fn into_token_tree(self) -> TokenTree {
22 let lit = if self { "true" } else { "false" };
23 Ident::new(lit, Span::mixed_site()).into()
24 }
25}
26
27impl ToTokenStream for TokenStream {
28 fn into_token_stream(self) -> TokenStream {
29 self
30 }
31}
32
33impl ToTokenTree for TokenTree {
34 fn into_token_tree(self) -> TokenTree {
35 self
36 }
37}
38
39impl ToTokenTree for &str {
40 fn into_token_tree(self) -> TokenTree {
41 TokenTree::Literal(Literal::string(self))
42 }
43}
44
45impl ToTokenStream for NonZero<u16> {
46 fn into_token_stream(self) -> TokenStream {
47 // Safety: `self.get()` cannot be zero because `self` is a `NonZero<u16>`.
48 quote! {
49 unsafe { ::core::num::NonZero::<u16>::new_unchecked(#(self.get())) }
50 }
51 }
52}
53
54macro_rules! impl_for_tree_types {
55 ($($type:ty)*) => {$(
56 impl ToTokenTree for $type {
57 fn into_token_tree(self) -> TokenTree {
58 self.into()
59 }
60 }
61 )*};
62}
63impl_for_tree_types![Ident Literal Group Punct];
64
65macro_rules! impl_for_int {
66 ($($type:ty => $method:ident)*) => {$(
67 impl ToTokenTree for $type {
68 fn into_token_tree(self) -> TokenTree {
69 Literal::$method(self).into()
70 }
71 }
72 )*};
73}
74impl_for_int! {
75 i8 => i8_unsuffixed
76 u8 => u8_unsuffixed
77 u16 => u16_unsuffixed
78 i32 => i32_unsuffixed
79 u32 => u32_unsuffixed
80 i64 => i64_unsuffixed
81}