Implement optionality for types.

This commit is contained in:
Jesse Brault 2025-09-03 17:12:19 -05:00
parent 3b07cef209
commit 9f3f3e0f0d
3 changed files with 25 additions and 15 deletions

View File

@ -46,7 +46,7 @@ fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
)) ))
} }
fn get_single_child_to_build(name: &str, rule: &str, build: &Yaml) -> SingleChildToBuild { fn get_single_child_to_build(name: &str, rule: &str, optional: bool, build: &Yaml) -> SingleChildToBuild {
if build.is_hash() { if build.is_hash() {
let r#type = build["type"].as_str().unwrap(); let r#type = build["type"].as_str().unwrap();
let var_name = build["var"] let var_name = build["var"]
@ -64,18 +64,17 @@ fn get_single_child_to_build(name: &str, rule: &str, build: &Yaml) -> SingleChil
} }
} else { } else {
match build.as_str() { match build.as_str() {
Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s)), Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s, optional)),
None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule)), None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule, optional)),
} }
} }
} }
fn get_single_child(name: &str, rule: &str, build: &Yaml, optional: bool) -> ChildSpec { fn get_single_child(name: &str, rule: &str, optional: bool, build: &Yaml) -> ChildSpec {
ChildSpec::SingleChild(SingleChild::new( ChildSpec::SingleChild(SingleChild::new(
name, name,
rule, rule,
get_single_child_to_build(name, rule, build), get_single_child_to_build(name, rule, optional, build),
optional
)) ))
} }
@ -111,7 +110,7 @@ fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> {
.as_bool() .as_bool()
.unwrap_or_else(|| false); .unwrap_or_else(|| false);
get_single_child(name, &rule, build, optional) get_single_child(name, &rule, optional, build)
} }
} else { } else {
ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap())) ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap()))

View File

@ -224,7 +224,6 @@ pub struct SingleChild {
name: String, name: String,
rule: String, rule: String,
build: SingleChildToBuild, build: SingleChildToBuild,
optional: bool
} }
impl SingleChild { impl SingleChild {
@ -234,17 +233,16 @@ impl SingleChild {
rule: name.to_case(Case::Pascal), rule: name.to_case(Case::Pascal),
build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule( build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
&name.to_case(Case::Pascal), &name.to_case(Case::Pascal),
false,
)), )),
optional: false,
} }
} }
pub fn new(name: &str, rule: &str, build: SingleChildToBuild, optional: bool) -> Self { pub fn new(name: &str, rule: &str, build: SingleChildToBuild) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
rule: rule.to_string(), rule: rule.to_string(),
build, build,
optional
} }
} }
@ -275,14 +273,16 @@ pub struct SingleTypeChildToBuild {
build: String, build: String,
var_name: String, var_name: String,
with: String, with: String,
optional: bool,
} }
impl SingleTypeChildToBuild { impl SingleTypeChildToBuild {
pub fn from_build_or_rule(build_or_rule: &str) -> Self { pub fn from_build_or_rule(build_or_rule: &str, optional: bool) -> Self {
Self { Self {
build: build_or_rule.to_string(), build: build_or_rule.to_string(),
var_name: build_or_rule.to_case(Case::Snake), var_name: build_or_rule.to_case(Case::Snake),
with: make_build_fn_name(build_or_rule), with: make_build_fn_name(build_or_rule),
optional,
} }
} }
@ -300,6 +300,11 @@ impl SingleTypeChildToBuild {
pub fn with(&self) -> &str { pub fn with(&self) -> &str {
&self.with &self.with
} }
/// If the type should be wrapped in an Option.
pub fn optional(&self) -> bool {
self.optional
}
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -64,9 +64,15 @@ fn handle_single_type_child(
let child_ident_mut = format_ident!("{}_mut", single_type_child.var_name()); let child_ident_mut = format_ident!("{}_mut", single_type_child.var_name());
let child_type_ident = format_ident!("{}", single_type_child.build()); let child_type_ident = format_ident!("{}", single_type_child.build());
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
annotated_members.push(quote! { if single_type_child.optional() {
#child_ident: Box<#child_type_ident> annotated_members.push(quote! {
}); #child_ident: Option<Box<#child_type_ident>>
});
} else {
annotated_members.push(quote! {
#child_ident: Box<#child_type_ident>
})
}
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> &#child_type_ident { pub fn #child_ident(&self) -> &#child_type_ident {
self.#child_ident.as_ref() self.#child_ident.as_ref()