use super::*;
use serde::Serialize;
use tera::Context;
#[derive(Debug, Serialize, PartialEq, Eq, Clone)]
pub enum RPCDataType {
Map,
List,
Msg,
Rpc,
}
#[derive(Debug, Serialize, PartialEq, Eq)]
pub struct GeneratedField {
pub name: String,
pub field_type: String,
pub comment: Option<String>,
}
impl GeneratedField {
pub fn new(name: String, field_type: String, comment: Option<String>) -> Result<Self> {
const RESERVED_WORDS: &[&str] = &["type"];
if RESERVED_WORDS.contains(&name.as_str()) {
anyhow::bail!("Field name {} is reserved words", &name)
}
Ok(Self {
name: name,
field_type: field_type,
comment,
})
}
}
#[derive(Debug, Serialize, PartialEq, Eq)]
pub struct GeneratedStruct {
pub name: String,
pub fields: Vec<GeneratedField>,
pub comment: Option<String>,
pub data_name: String,
pub rpc_type: RPCDataType,
pub return_type: Option<String>,
}
impl GeneratedStruct {
pub fn new(
data_name: &str,
fields: Vec<GeneratedField>,
comment: Option<String>,
ty: RPCDataType,
rt: Option<String>,
) -> Self {
Self {
name: kebab_to_pascal_case(data_name),
fields,
comment,
data_name: data_name.to_string(),
rpc_type: ty,
return_type: rt.as_ref().map(|x| kebab_to_pascal_case(x)),
}
}
pub fn insert_template(&self, ctx: &mut Context) {
ctx.insert("name", &self.name);
ctx.insert("fields", &self.fields);
match self.rpc_type {
RPCDataType::Map => {
ctx.insert("ty", "map");
}
RPCDataType::List => {
ctx.insert("ty", "list");
}
RPCDataType::Msg => {
ctx.insert("data_name", &self.data_name);
ctx.insert("ty", "msg");
}
RPCDataType::Rpc => {
ctx.insert("data_name", &self.data_name);
ctx.insert("ty", "rpc");
ctx.insert(
"return_type",
&self.return_type.as_ref().map_or("()", |v| v),
)
}
}
}
pub fn gen_code_with_files(&self, template_files: &[impl AsRef<Path>]) -> Result<String> {
let mut tera = Tera::default();
let mut context = Context::new();
let mut all_temps = vec![];
for p in template_files {
match p.as_ref().file_stem().map(|n| n.to_str()) {
Some(n) => {
all_temps.push((p, n));
}
None => (),
}
}
tera.add_template_files(all_temps)?;
let mut result = String::new();
self.insert_template(&mut context);
result += &tera.render("def_struct.rs", &context)?;
result += "\n\n";
result += &tera.render("rpc_impl", &context)?;
Ok(result)
}
pub fn gen_code_with_tera(&self, templates: &Tera) -> Result<String> {
let mut context = Context::new();
let mut result = String::new();
self.insert_template(&mut context);
result += &templates.render("def_struct.rs", &context)?;
result += "\n\n";
result += &templates.render("rpc_impl", &context)?;
Ok(result)
}
}