use darling::{FromDeriveInput, FromField, FromVariant};
use syn::{DeriveInput, Expr};
#[derive(Debug, FromDeriveInput)]
#[darling(attributes(frame))]
pub struct ContainerAttrs {
pub error: syn::Path,
}
pub fn get_repr(input: &DeriveInput) -> syn::Path {
input
.attrs
.iter()
.find(|a| a.path().is_ident("repr"))
.and_then(|a| a.parse_args::<syn::Path>().ok())
.unwrap_or_else(|| syn::parse_quote!(u8))
}
#[derive(Debug, Default, FromField)]
#[darling(attributes(frame), default)]
pub struct FieldAttrs {
pub read_all: bool,
pub length: Option<Expr>,
pub skip: bool,
}
impl FieldAttrs {
pub fn validate(&self, field_name: &str) -> Result<(), darling::Error> {
if self.read_all && self.length.is_some() {
return Err(darling::Error::custom(format!(
"field `{field_name}`: `read_all` and `length` are mutually exclusive"
)));
}
if self.skip && (self.read_all || self.length.is_some()) {
return Err(darling::Error::custom(format!(
"field `{field_name}`: `skip` cannot be combined with `read_all` or `length`"
)));
}
Ok(())
}
}
#[derive(Debug, Default, FromVariant)]
#[darling(attributes(frame), default)]
pub struct VariantAttrs {
pub id: Option<Expr>,
pub id_pat: Option<syn::LitStr>,
pub decode_inner: bool,
}
impl VariantAttrs {
pub fn validate(&self, variant_name: &str) -> Result<(), darling::Error> {
match (&self.id, &self.id_pat) {
(None, None) => Err(darling::Error::custom(format!(
"variant `{variant_name}`: must have `#[frame(id = \"...\")]` or `#[frame(id_pat = \"...\")]`"
))),
(Some(_), Some(_)) => Err(darling::Error::custom(format!(
"variant `{variant_name}`: `id` and `id_pat` are mutually exclusive"
))),
_ => Ok(()),
}
}
}