procmeta-core 0.3.5

proc-macro helper
Documentation
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>)
    }
}