use crate::helper::{is_option, type_path_replace_crate};
use crate::parsed_input::FieldHandling::{IsOption, Other, Required};
use crate::FieldHelperAttributes;
use darling::FromAttributes;
use proc_macro2::Ident;
use std::iter;
use syn::{Error, Field, Fields, Path};
#[derive(Debug, Clone)]
pub(crate) enum FieldHandling {
Required,
IsOption,
Other,
}
#[derive(Debug, PartialEq)]
pub(crate) enum StructType {
Named,
Unnamed,
Unit,
}
#[derive(Debug, Clone)]
pub(crate) struct FieldParsed {
pub field: Field,
pub handling: FieldHandling,
}
#[derive(Debug)]
pub(crate) struct StructParsed {
pub crate_name: Path,
pub struct_type: StructType,
pub fields: Vec<FieldParsed>,
}
pub(crate) fn into_field_handling(
crate_name: Path,
fields: Fields,
input_crate_replacement: Option<&Ident>,
) -> Result<StructParsed, Error> {
let struct_named = match &fields {
Fields::Named(_) => StructType::Named,
Fields::Unnamed(_) => StructType::Unnamed,
Fields::Unit => StructType::Unit,
};
let fields_iter: Box<dyn Iterator<Item = Field>> = match fields {
Fields::Named(f) => Box::new(f.named.into_iter()),
Fields::Unnamed(f) => Box::new(f.unnamed.into_iter()),
Fields::Unit => Box::new(iter::empty()),
};
let fields_with_handling = fields_iter
.map(|mut field| {
let attrs = FieldHelperAttributes::from_attributes(&field.attrs)?;
if let Some(input_crate_replacement) = input_crate_replacement {
type_path_replace_crate(&mut field.ty, input_crate_replacement);
}
let handling = if attrs.required.is_some() {
Required
} else if is_option(&field.ty) {
IsOption
} else {
Other
};
Ok::<_, Error>(FieldParsed { field, handling })
})
.collect::<Result<Vec<_>, _>>()?;
Ok(StructParsed {
crate_name,
struct_type: struct_named,
fields: fields_with_handling,
})
}