use proc_macro2::{Ident, Literal, Span, TokenStream};
use quote::{quote, TokenStreamExt};
pub trait ToTokenStream {
fn to_toks(&self, toks: &mut TokenStream);
fn to_tok_stream(&self) -> TokenStream {
let mut tokens = TokenStream::new();
self.to_toks(&mut tokens);
tokens
}
fn to_tokens(&self, toks: &mut TokenStream) {
self.to_toks(toks);
}
}
macro_rules! primitive {
($($t:ty => $name:ident)*) => {
$(
impl ToTokenStream for $t {
fn to_toks(&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
char => character
&str => string
}
impl ToTokenStream for bool {
fn to_toks(&self, tokens: &mut TokenStream) {
tokens.append(Ident::new(&self.to_string(), Span::call_site()));
}
}
impl<'a, T: ?Sized + ToTokenStream> ToTokenStream for &'a T {
fn to_toks(&self, tokens: &mut TokenStream) {
(**self).to_toks(tokens);
}
}
impl<'a, T: ?Sized + ToTokenStream> ToTokenStream for &'a mut T {
fn to_toks(&self, tokens: &mut TokenStream) {
(**self).to_toks(tokens);
}
}
fn to_toks_slice<T>(sl: &[T], tokens: &mut TokenStream)
where
T: ToTokenStream,
{
let mut arr_toks = TokenStream::new();
for a in sl.iter() {
let a_toks = a.to_tok_stream();
let element = quote! { #a_toks, };
arr_toks.extend(element);
}
let element = quote! { [#arr_toks] };
tokens.extend(element);
}
impl<T> ToTokenStream for &[T]
where
T: ToTokenStream,
{
fn to_toks(&self, tokens: &mut TokenStream) {
to_toks_slice(self, tokens);
}
}
impl<T, const N: usize> ToTokenStream for [T; N]
where
T: ToTokenStream,
{
fn to_toks(&self, tokens: &mut TokenStream) {
to_toks_slice(self, tokens);
}
}
impl ToTokenStream for String {
fn to_toks(&self, tokens: &mut TokenStream) {
tokens.extend(quote! { #self });
}
}
impl<T> ToTokenStream for Vec<T>
where
T: ToTokenStream,
{
fn to_toks(&self, tokens: &mut TokenStream) {
let mut arr_toks = TokenStream::new();
for a in self {
let a_toks = a.to_tok_stream();
let element = quote! { #a_toks, };
arr_toks.extend(element);
}
let element = quote! { vec![#arr_toks] };
tokens.extend(element);
}
}
impl<T> ToTokenStream for Option<T>
where
T: ToTokenStream,
{
fn to_toks(&self, tokens: &mut TokenStream) {
let element;
match self {
Some(a) => {
let a_toks = a.to_tok_stream();
element = quote! {
Some(#a_toks)
};
}
None => {
element = quote! { None };
}
}
tokens.extend(element);
}
}
macro_rules! build_tuple_trait {
($($id:ident),+;$($index:literal),+) => {
fn to_toks(&self, tokens: &mut TokenStream) {
let ($($id),+) = self;
$(let $id = $id.to_tok_stream();)+
let element = quote! { ($(#$id),+) };
tokens.extend(element);
}
};
}
impl<T1, T2> ToTokenStream for (T1, T2)
where
T1: ToTokenStream,
T2: ToTokenStream,
{
build_tuple_trait!(t1, t2; 0, 1);
}
impl<T1, T2, T3> ToTokenStream for (T1, T2, T3)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3; 0, 1, 2);
}
impl<T1, T2, T3, T4> ToTokenStream for (T1, T2, T3, T4)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4; 0, 1, 2, 3);
}
impl<T1, T2, T3, T4, T5> ToTokenStream for (T1, T2, T3, T4, T5)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5; 0, 1, 2, 3, 4);
}
impl<T1, T2, T3, T4, T5, T6> ToTokenStream for (T1, T2, T3, T4, T5, T6)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6; 0, 1, 2, 3, 4, 5);
}
impl<T1, T2, T3, T4, T5, T6, T7> ToTokenStream for (T1, T2, T3, T4, T5, T6, T7)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7; 0, 1, 2, 3, 4, 5, 6);
}
impl<T1, T2, T3, T4, T5, T6, T7, T8> ToTokenStream for (T1, T2, T3, T4, T5, T6, T7, T8)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
T8: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7, t8; 0, 1, 2, 3, 4, 5, 6, 7);
}
impl<T1, T2, T3, T4, T5, T6, T7, T8, T9> ToTokenStream for (T1, T2, T3, T4, T5, T6, T7, T8, T9)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
T8: ToTokenStream,
T9: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7, t8, t9; 0, 1, 2, 3, 4, 5, 6, 7, 8);
}
impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ToTokenStream
for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
T8: ToTokenStream,
T9: ToTokenStream,
T10: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
}
impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> ToTokenStream
for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
T8: ToTokenStream,
T9: ToTokenStream,
T10: ToTokenStream,
T11: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
impl<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> ToTokenStream
for (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)
where
T1: ToTokenStream,
T2: ToTokenStream,
T3: ToTokenStream,
T4: ToTokenStream,
T5: ToTokenStream,
T6: ToTokenStream,
T7: ToTokenStream,
T8: ToTokenStream,
T9: ToTokenStream,
T10: ToTokenStream,
T11: ToTokenStream,
T12: ToTokenStream,
{
build_tuple_trait!(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
}