1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::collections::HashMap;

use proc_macro2::TokenStream;
use quote::quote;
use syn::{Field, Type};

use crate::util::type_add_colon2;

pub trait GetTypeColon2 {
    fn get_type_colon2(&self) -> Type;
}

impl GetTypeColon2 for Field {
    fn get_type_colon2(&self) -> Type {
        let mut ty = self.ty.clone();
        type_add_colon2(&mut ty);
        ty
    }
}

pub trait GetTokenStream {
    fn get_token_stream(self) -> TokenStream;

    fn get_self_ty() -> TokenStream;
}

macro_rules! impl_get_token_stream {
    ($ty: ty) => {
        impl GetTokenStream for $ty {
            fn get_token_stream(self) -> TokenStream {
                quote!(#self)
            }

            fn get_self_ty() -> TokenStream {
                quote!($ty)
            }
        }
    };
}

impl_get_token_stream!(bool);
impl_get_token_stream!(u8);
impl_get_token_stream!(u16);
impl_get_token_stream!(u32);
impl_get_token_stream!(usize);
impl_get_token_stream!(u64);
impl_get_token_stream!(u128);
impl_get_token_stream!(i8);
impl_get_token_stream!(i16);
impl_get_token_stream!(i32);
impl_get_token_stream!(i64);
impl_get_token_stream!(i128);
impl_get_token_stream!(f32);
impl_get_token_stream!(f64);
impl_get_token_stream!(&str);

impl<K: GetTokenStream, V: GetTokenStream> GetTokenStream for HashMap<K, V> {
    fn get_token_stream(self) -> TokenStream {
        if self.is_empty() {
            return quote!(HashMap::new());
        }
        let mut result = quote!();
        for (k, v) in self.into_iter() {
            let k_token = k.get_token_stream();
            let v_token = v.get_token_stream();
            result = quote! {
                #result
                map.insert(#k_token, #v_token);
            };
        }
        quote!({
            let mut map = std::collections::HashMap::new();
            #result
            map
        })
    }

    fn get_self_ty() -> TokenStream {
        let k = K::get_self_ty();
        let v = V::get_self_ty();
        quote!(HashMap::<#k, #v>)
    }
}

impl GetTokenStream for String {
    fn get_token_stream(self) -> TokenStream {
        quote!(#self.into())
    }

    fn get_self_ty() -> TokenStream {
        quote!(String)
    }
}

impl<T: GetTokenStream> GetTokenStream for Option<T> {
    fn get_token_stream(self) -> TokenStream {
        match self {
            Some(v) => {
                let v_token_stream = v.get_token_stream();
                quote!(Some(#v_token_stream))
            }
            None => quote!(None),
        }
    }

    fn get_self_ty() -> TokenStream {
        let t = T::get_self_ty();
        quote!(Option::<#t>)
    }
}

impl<T: GetTokenStream> GetTokenStream for Vec<T> {
    fn get_token_stream(self) -> TokenStream {
        let mut items = quote!();
        for item in self {
            let item_token_stream = item.get_token_stream();
            items = quote!(#items #item_token_stream,);
        }
        quote!(vec![#items])
    }

    fn get_self_ty() -> TokenStream {
        let t = T::get_self_ty();
        quote!(Vec::<#t>)
    }
}