use darling::FromAttributes;
use proc_macro2::{Ident, TokenStream};
use syn::{parse2, Field, Generics, ItemStruct, LitInt, LitStr, Type, Visibility};
use crate::parse::annotations::{Default, Index, OnAction};
use crate::parse::get_fields_named;
pub fn parse_model(tokens: TokenStream) -> darling::Result<ParsedModel> {
let ItemStruct {
struct_token: _,
generics,
fields,
ident,
vis,
attrs,
semi_token: _,
} = parse2(tokens)?;
let mut errors = darling::Error::accumulator();
let annos = errors
.handle(ModelAnnotations::from_attributes(&attrs))
.unwrap_or_default();
let mut parsed_fields = Vec::new();
if let Some(raw_fields) = errors.handle(get_fields_named(fields)) {
parsed_fields.reserve_exact(raw_fields.named.len());
for field in raw_fields.named {
let Field {
attrs,
vis,
mutability: _,
ident,
colon_token: _,
ty,
} = field;
let Some(annos) = errors.handle(ModelFieldAnnotations::from_attributes(&attrs)) else {
continue;
};
let ident = ident.expect("Fields::Named should contain named fields");
parsed_fields.push(ParsedField {
vis,
ident,
ty,
annos,
});
}
}
errors.finish_with(ParsedModel {
vis,
ident,
generics,
annos,
fields: parsed_fields,
})
}
pub struct ParsedModel {
pub vis: Visibility,
pub ident: Ident,
pub generics: Generics,
pub annos: ModelAnnotations,
pub fields: Vec<ParsedField>,
}
#[derive(FromAttributes, Debug, Default)]
#[darling(attributes(rorm), default)]
pub struct ModelAnnotations {
pub rename: Option<LitStr>,
pub experimental_unregistered: bool,
pub experimental_generics: bool,
}
pub struct ParsedField {
pub vis: Visibility,
pub ident: Ident,
pub ty: Type,
pub annos: ModelFieldAnnotations,
}
#[derive(FromAttributes, Debug, Default)]
#[darling(attributes(rorm), default)]
pub struct ModelFieldAnnotations {
pub auto_create_time: bool,
pub auto_update_time: bool,
pub auto_increment: bool,
pub primary_key: bool,
pub unique: bool,
pub id: bool,
pub on_delete: Option<OnAction>,
pub on_update: Option<OnAction>,
pub rename: Option<LitStr>,
pub default: Option<Default>,
pub max_length: Option<LitInt>,
pub index: Option<Index>,
}