use proc_macro::TokenStream;
use quote::quote;
use syn::{
parse_macro_input, punctuated::Punctuated, token::Comma, DeriveInput, GenericParam,
Generics, TypeParamBound,
};
pub fn derive_from_str_json(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let generics = &input.generics;
let params = deserialize_in_generics(generics);
let result = quote! {
impl<#params> std::str::FromStr for #name #generics {
type Err = serde_json::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
};
TokenStream::from(result)
}
fn deserialize_in_generics(g: &Generics) -> Punctuated<GenericParam, Comma> {
let mut params = Punctuated::<GenericParam, Comma>::new();
for param in g.params.iter() {
let param = match param {
GenericParam::Type(typ) => {
let mut typ = typ.clone();
typ.bounds.push(TypeParamBound::Trait(
syn::parse_str("serde::de::DeserializeOwned").unwrap(),
));
GenericParam::Type(typ.clone())
}
_ => param.clone(),
};
params.push(param);
}
params
}