use super::{pk_to_string, pk_use_import, type_map, FieldDef};
pub fn gen(
pascal: &str,
snake: &str,
fields: &[FieldDef],
id: Option<&str>,
timestamps: bool,
) -> String {
let id_resource_type = match id {
Some(_) => "String",
None => "i64",
};
let id_from = pk_to_string(id);
let mut struct_fields = format!(" pub id: {},\n", id_resource_type);
let mut from_fields = format!(" id: {},\n", id_from);
for f in fields {
let tm = type_map(&f.field_type);
let base_res_t = match f.field_type.as_str() {
"datetime" | "date" => "String",
"json" => "serde_json::Value",
_ => tm.resource_type,
};
let (res_t, from_expr) = if f.optional {
let opt_t = format!("Option<{base_res_t}>");
let expr = match f.field_type.as_str() {
"datetime" => format!("m.{}.map(|v| v.to_rfc3339())", f.name),
"date" => format!("m.{}.map(|v| v.to_string())", f.name),
_ => format!("m.{}", f.name),
};
(opt_t, expr)
} else {
let expr = match f.field_type.as_str() {
"datetime" => format!("m.{}.to_rfc3339()", f.name),
"date" => format!("m.{}.to_string()", f.name),
_ => format!("m.{}", f.name),
};
(base_res_t.to_string(), expr)
};
struct_fields.push_str(&format!(" pub {}: {},\n", f.name, res_t));
from_fields.push_str(&format!(" {}: {},\n", f.name, from_expr));
}
if timestamps {
struct_fields.push_str(" pub created_at: String,\n");
struct_fields.push_str(" pub updated_at: String,\n");
from_fields.push_str(" created_at: m.created_at.to_rfc3339(),\n");
from_fields.push_str(" updated_at: m.updated_at.to_rfc3339(),\n");
}
let mut uses = String::from("use serde::Serialize;\n");
let pk_use = pk_use_import(id);
if !pk_use.is_empty() {
uses.push_str(pk_use);
}
let _ = snake;
format!(
"{uses}\n#[derive(Debug, Serialize)]\npub struct {pascal}Resource {{\n{struct_fields}}}\n\nimpl {pascal}Resource {{\n pub fn from(m: super::super::models::{pascal}) -> Self {{\n Self {{\n{from_fields} }}\n }}\n}}\n"
)
}