use super::formatter::{DefaultPropsFormatter, PropsFormatter};
mod props;
mod vars;
pub use props::*;
pub use vars::*;
pub enum TsainPattern {
Enum(EnumPattern),
Struct(PropsPattern),
}
pub struct Composition<T> {
rs_name: &'static str,
ts_name: &'static str,
type_args: Vec<&'static str>,
list: T,
skip_brand: bool,
extra_brands: Vec<[&'static str; 2]>,
}
impl<T> Composition<T> {
pub fn new(
rs_name: &'static str,
ts_name: &'static str,
type_args: Vec<&'static str>,
list: T,
skip_brand: bool,
extra_brands: Vec<[&'static str; 2]>,
) -> Self {
Self {
rs_name,
ts_name,
type_args,
list,
skip_brand,
extra_brands,
}
}
fn build_brands_script(&self) -> String {
let mut pairs = Vec::new();
if !self.skip_brand {
pairs.push(format!(r#"readonly __brand: "{}""#, self.ts_name));
}
pairs.extend(
self.extra_brands.iter().map(|[brand_name, brand_ts_type]| {
format!("readonly {brand_name}: {brand_ts_type}")
}),
);
if pairs.is_empty() {
Default::default()
} else {
let pairs = pairs.join(", ");
format!(" & {{{}}}", pairs)
}
}
}
impl TsainPattern {
pub fn new_enum(
rs_name: &'static str,
ts_name: &'static str,
type_args: Vec<&'static str>,
list: Vec<Option<(&'static str, PropsPattern)>>,
) -> Self {
Self::Enum(EnumPattern::new(
rs_name,
ts_name,
type_args,
list,
true,
Default::default(),
))
}
pub fn new_struct(
rs_name: &'static str,
ts_name: &'static str,
type_args: Vec<&'static str>,
list: Vec<(&'static str, &'static str)>,
skip_brand: bool,
extra_brands: Vec<[&'static str; 2]>,
) -> Self {
Self::Struct(PropsPattern::new(
rs_name,
ts_name,
type_args,
list,
skip_brand,
extra_brands,
))
}
pub fn rs_name(&self) -> &str {
match self {
Self::Enum(Composition { rs_name, .. }) | Self::Struct(Composition { rs_name, .. }) => {
rs_name
}
}
}
pub fn format_type_script(&self) -> String {
match self {
Self::Enum(e) => e.format_enum_type_script(&DefaultPropsFormatter),
Self::Struct(e) => DefaultPropsFormatter.format_type_script(e, None),
}
}
}