use super::*;
pub type PropsPattern = Composition<Vec<(&'static str, &'static str)>>;
impl PropsPattern {
pub fn list(&self) -> &Vec<(&'static str, &'static str)> {
&self.list
}
fn prop_names(&self) -> String {
self.list
.iter()
.map(|(n, _)| *n)
.collect::<Vec<_>>()
.join(", ")
}
fn prop_types(&self) -> String {
self.list
.iter()
.map(|(_, t)| *t)
.collect::<Vec<_>>()
.join(", ")
}
fn prop_name2types(&self) -> String {
self.list
.iter()
.map(|(n, t)| format!("{n}: {t}"))
.collect::<Vec<_>>()
.join(", ")
}
}
impl PropsPattern {
fn default_declaration_script(&self, var_id: Option<u32>) -> String {
let ts_name = &self.ts_name;
let prop_types = self.prop_types();
let type_args = crate::format_type_args(&self.type_args);
let brands_script = self.build_brands_script();
match var_id {
None => format!(r#"export type {ts_name}{type_args} = [{prop_types}]{brands_script};"#),
Some(var_id) => format!(
r#"export type {ts_name}{type_args} = [{var_id}, [{prop_types}]]{brands_script};"#
),
}
}
fn default_constructor_name(&self) -> String {
format!("{}_", self.ts_name)
}
fn default_constructor_script(&self, var_id: Option<u32>) -> String {
let ts_name = &self.ts_name;
let type_args = crate::format_type_args(&self.type_args);
let constructor_name = self.default_constructor_name();
let prop_names = self.prop_names();
let prop_name2types = self.prop_name2types();
match var_id {
None => format!(
"export const {constructor_name} = {type_args}({prop_name2types}) => [{prop_names}] as {ts_name}{type_args};"
),
Some(var_id) => format!(
"export const {constructor_name} = {type_args}({prop_name2types}) => [{var_id}, [{prop_names}]] as {ts_name}{type_args};"
),
}
}
fn default_prop_getter_script(
&self,
prop_name: &str,
prop_type: &str,
prop_idx: usize,
is_variant: bool,
) -> String {
let ts_name = &self.ts_name;
let type_args = crate::format_type_args(&self.type_args);
let mut script = format!("export const {ts_name}_{prop_name}_id: number = {prop_idx};\n");
let getter = match is_variant {
false => {
format!(
"export const {ts_name}_{prop_name} = {type_args}(v: {ts_name}{type_args}): {prop_type} => v[{prop_idx}];\n"
)
}
true => {
format!(
"export const {ts_name}_{prop_name} = {type_args}(v: {ts_name}{type_args}): {prop_type} => v[1][{prop_idx}];\n"
)
}
};
script.push_str(&getter);
return script;
}
fn default_prop_getters_script(&self, is_variant: bool) -> String {
self.list
.iter()
.enumerate()
.map(|(i, (name, ty))| self.default_prop_getter_script(name, ty, i, is_variant))
.collect::<Vec<_>>()
.join("\n")
}
pub(crate) fn default_as_variant_script(
&self,
enum_ts_name: &str,
enum_type_args: &str,
var_id: u32,
) -> String {
let ts_name = self.ts_name;
let type_args = crate::format_type_args(&self.type_args);
format!(
"export const as{ts_name} = {enum_type_args}(e: {enum_ts_name}{enum_type_args}): {ts_name}{type_args} | undefined => e[0] == {var_id} ? e as {ts_name}{type_args} : undefined;"
)
}
}
impl PropsFormatter for DefaultPropsFormatter {
fn props_head_script(&self, props: &PropsPattern, var_id: Option<u32>) -> String {
let ts_name = &props.ts_name;
match var_id {
None => format!("// # Struct {ts_name}"),
Some(var_id) => format!("// ## Variant {var_id}: {ts_name}"),
}
}
fn props_script_list(
&self,
props: &PropsPattern,
var_id: Option<u32>,
) -> Vec<(String, String)> {
vec![
(
format!("// 1. Type"),
props.default_declaration_script(var_id),
),
(
format!("// 2. Constructor"),
props.default_constructor_script(var_id),
),
(
format!("// 3. Getters"),
props.default_prop_getters_script(var_id.is_some()),
),
]
}
fn as_variant_script(
&self,
props: &PropsPattern,
enum_ts_name: &str,
enum_type_args: &str,
var_id: u32,
) -> String {
props.default_as_variant_script(enum_ts_name, enum_type_args, var_id)
}
}