use darling::{
ast,
util::{PathList, SpannedValue},
FromDeriveInput, FromField, FromMeta,
};
use quote::format_ident;
use syn::{Generics, Ident, Type, Visibility};
#[derive(Debug, FromDeriveInput)]
#[darling(
attributes(table),
supports(struct_named, struct_newtype, struct_tuple)
)]
pub struct StructTable {
pub ident: Ident,
pub vis: Visibility,
pub generics: Generics,
pub data: ast::Data<(), TableColumn>,
#[darling(default)]
pub name: Option<String>,
#[darling(default)]
pub skip_parts: Option<SpannedValue<()>>,
#[darling(default, rename = "data")]
pub data_attr: Option<TableDataAttr>,
#[darling(default)]
pub derive: Option<PathList>,
#[darling(default)]
pub mode: TableMode,
}
impl StructTable {
pub fn as_style(&self) -> darling::ast::Style {
self.data
.as_ref()
.take_struct()
.map(|fields| fields.style)
.expect("BUG: Identified struct but data missing!")
}
pub fn to_table_name(&self) -> Ident {
self.name
.as_ref()
.map(|x| format_ident!("{}", x))
.unwrap_or_else(|| format_ident!("{}Table", &self.ident))
}
pub fn to_table_data_name(&self) -> Ident {
self.data_attr
.as_ref()
.and_then(|x| x.name.as_ref())
.map(|x| format_ident!("{}", x))
.unwrap_or_else(|| format_ident!("{}TableData", &self.ident))
}
pub fn columns(&self) -> Vec<&TableColumn> {
let x = self.data.as_ref().take_struct();
x.unwrap().fields
}
}
#[derive(Debug, Default, FromMeta)]
#[darling(default)]
pub struct TableDataAttr {
#[darling(default)]
pub name: Option<String>,
#[darling(default)]
pub derive: Option<PathList>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromMeta)]
#[darling(rename_all = "snake_case")]
pub enum TableMode {
Dynamic,
FixedColumn,
Fixed { rows: usize },
}
impl Default for TableMode {
fn default() -> Self {
Self::Dynamic
}
}
#[derive(Debug, FromField)]
#[darling(attributes(column))]
pub struct TableColumn {
pub ident: Option<Ident>,
pub ty: Type,
#[darling(default)]
pub indexed: Option<SpannedValue<()>>,
#[darling(default)]
pub name: Option<String>,
}