refactor: remove type name input from the helper attribute

This commit is contained in:
naskya 2024-07-16 01:53:48 +09:00
parent f8d7b40722
commit 988bfc3380
Signed by: naskya
GPG key ID: 712D413B3A9FED5C

View file

@ -135,21 +135,15 @@ fn derive_impl(input: syn::DeriveInput) -> syn::Result<TokenStream> {
let vis = &field.vis; let vis = &field.vis;
let ty = &field.ty; let ty = &field.ty;
let relax_attr = field if field.attrs.iter().any(|attr| attr.path().is_ident("relax")) {
.attrs // nested
.iter() Ok(quote! { #vis #name: ::std::option::Option<<#ty as ::relax::Relax>::Partial> })
.find(|attr| attr.path().is_ident("relax")); } else {
if relax_attr.is_none() {
// not nested // not nested
match get_generic_ty("Option", ty) { match get_generic_ty("Option", ty) {
Some(ty) => Ok(quote! { #vis #name: ::std::option::Option<#ty> }), Some(ty) => Ok(quote! { #vis #name: ::std::option::Option<#ty> }),
None => Ok(quote! { #vis #name: ::std::option::Option<#ty> }), None => Ok(quote! { #vis #name: ::std::option::Option<#ty> }),
} }
} else {
// nested
let ty = get_ty_name_from_helper_attr(relax_attr.unwrap())?;
Ok(quote! { #vis #name: ::std::option::Option<#ty> })
} }
}) })
.collect::<syn::Result<Vec<_>>>()?; .collect::<syn::Result<Vec<_>>>()?;
@ -169,18 +163,16 @@ fn derive_impl(input: syn::DeriveInput) -> syn::Result<TokenStream> {
let try_from_fields = fields.iter().map(|field| -> syn::Result<TokenStream> { let try_from_fields = fields.iter().map(|field| -> syn::Result<TokenStream> {
let name = field.ident.as_ref(); let name = field.ident.as_ref();
let ty = &field.ty; let ty = &field.ty;
let relaxed_ty = field let nested = field
.attrs .attrs
.iter() .iter()
.find(|attr| attr.path().is_ident("relax")) .any(|attr| attr.path().is_ident("relax"));
.map(get_ty_name_from_helper_attr)
.transpose()?;
Ok(match (relaxed_ty, get_generic_ty("Option", ty)) { Ok(match (nested, get_generic_ty("Option", ty).is_some()) {
(None, None) => quote! { #name: value.#name.ok_or(::relax::RequiredFieldNotSet(stringify!(#name)))? }, (false, false) => quote! { #name: value.#name.ok_or(::relax::MissingRequiredField(stringify!(#name)))? },
(None, Some(_)) => quote! { #name: value.#name }, (false, true) => quote! { #name: value.#name },
(Some(_), None) => quote! { #name: value.#name.ok_or(::relax::RequiredFieldNotSet(stringify!(#name)))?.try_into()? }, (true, false) => quote! { #name: value.#name.ok_or(::relax::MissingRequiredField(stringify!(#name)))?.try_into()? },
(Some(_), Some(_)) => quote! { #name: value.#name.map(|val| val.try_into()).transpose().ok().flatten() }, (true, true) => quote! { #name: value.#name.map(|val| val.try_into()).transpose().ok().flatten() },
}) })
}).collect::<syn::Result<Vec<_>>>()?; }).collect::<syn::Result<Vec<_>>>()?;
@ -204,7 +196,7 @@ fn derive_impl(input: syn::DeriveInput) -> syn::Result<TokenStream> {
} }
impl #generics ::std::convert::TryFrom<#partial #generics> for #base #generics { impl #generics ::std::convert::TryFrom<#partial #generics> for #base #generics {
type Error = ::relax::RequiredFieldNotSet; type Error = ::relax::MissingRequiredField;
fn try_from(value: #partial) -> ::std::result::Result<Self, Self::Error> { fn try_from(value: #partial) -> ::std::result::Result<Self, Self::Error> {
Ok(Self{ Ok(Self{
@ -250,29 +242,3 @@ fn get_generic_ty<'a>(wrapper: &str, ty: &'a syn::Type) -> Option<&'a syn::Type>
None None
} }
} }
fn get_ty_name_from_helper_attr(attr: &syn::Attribute) -> syn::Result<TokenTree> {
let tokens = match attr {
syn::Attribute {
meta: syn::Meta::List(syn::MetaList { ref tokens, .. }),
..
} => tokens,
_ => {
return Err(syn::Error::new_spanned(
attr,
"helper attribute should be #[relax(StructName)]",
))
}
};
let tokens: Vec<TokenTree> = tokens.clone().into_iter().collect();
if tokens.len() != 1 {
return Err(syn::Error::new_spanned(
attr,
"helper attribute should be #[relax(StructName)]",
));
}
Ok(tokens[0].to_owned())
}