validators-derive 0.26.0

The provided crate offers a procedural macro for defining validators, including optional parameters.
use syn::{Meta, Token, punctuated::Punctuated};

use crate::{
    common::{rocket_options::RocketOptions, serde_options::SerdeOptions, tri_allow::TriAllow},
    panic,
};

pub(crate) struct IpXXAttribute {
    pub(crate) local:          TriAllow,
    pub(crate) port:           TriAllow,
    #[cfg_attr(not(feature = "serde"), allow(dead_code))]
    pub(crate) serde_options:  SerdeOptions,
    #[cfg_attr(not(feature = "rocket"), allow(dead_code))]
    pub(crate) rocket_options: RocketOptions,
}

impl IpXXAttribute {
    pub(crate) fn build_from_meta(meta: &Meta) -> syn::Result<Self> {
        let correct_parameters = ["local", "port", "serde", "rocket"];

        let mut local = TriAllow::Allow;
        let mut port = TriAllow::Allow;
        let mut serde_options = SerdeOptions::default();
        let mut rocket_options = RocketOptions::default();

        match meta {
            Meta::Path(_) => (),
            Meta::NameValue(_) => {
                return Err(panic::attribute_incorrect_format(meta.path()));
            },
            Meta::List(list) => {
                let result =
                    list.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;

                let mut local_is_set = false;
                let mut port_is_set = false;
                let mut serde_options_is_set = false;
                let mut rocket_options_is_set = false;

                let mut handler = |meta: &Meta| -> syn::Result<bool> {
                    if let Some(ident) = meta.path().get_ident() {
                        match ident.to_string().as_str() {
                            "local" => {
                                let v = TriAllow::from_meta(meta)?;

                                if local_is_set {
                                    return Err(panic::parameter_reset(ident));
                                }

                                local_is_set = true;

                                local = v;

                                return Ok(true);
                            },
                            "port" => {
                                let v = TriAllow::from_meta(meta)?;

                                if port_is_set {
                                    return Err(panic::parameter_reset(ident));
                                }

                                port_is_set = true;

                                port = v;

                                return Ok(true);
                            },
                            "serde" => {
                                let v = SerdeOptions::from_meta(meta)?;

                                if serde_options_is_set {
                                    return Err(panic::parameter_reset(ident));
                                }

                                serde_options_is_set = true;

                                serde_options = v;

                                return Ok(true);
                            },
                            "rocket" => {
                                let v = RocketOptions::from_meta(meta)?;

                                if rocket_options_is_set {
                                    return Err(panic::parameter_reset(ident));
                                }

                                rocket_options_is_set = true;

                                rocket_options = v;

                                return Ok(true);
                            },
                            _ => (),
                        }
                    }

                    Ok(false)
                };

                for p in result {
                    if !handler(&p)? {
                        return Err(panic::parameter_incorrect_format(
                            p.path(),
                            &correct_parameters,
                        ));
                    }
                }
            },
        }

        Ok(Self {
            local,
            port,
            serde_options,
            rocket_options,
        })
    }
}