use super::tao::TaoConfig;
use crate::codegen::template::basic::{AtomicFragment, FileFragment};
use indoc::formatdoc;
use std::cell::RefCell;
use std::rc::Rc;
pub struct DataFormatConfig {
pub tao_cfg: TaoConfig,
pub rust_primitive_unboxed_name: Rc<str>,
pub rust_primitive_boxed_name: Rc<str>,
pub default_value: Rc<str>,
pub explicit_rc: bool,
}
impl Default for DataFormatConfig {
fn default() -> Self {
Self {
tao_cfg: TaoConfig::default(),
rust_primitive_unboxed_name: Rc::from(""),
rust_primitive_boxed_name: Rc::from(""),
default_value: Rc::from(""),
explicit_rc: true,
}
}
}
fn data_concept_fragment(cfg: &DataFormatConfig) -> AtomicFragment {
let strongvalue_init = if cfg.explicit_rc {
format!(
"StrongValue::new_rc(Rc::<{}>::from(value))",
cfg.rust_primitive_boxed_name
)
} else {
"StrongValue::new(value)".to_owned()
};
AtomicFragment {
imports: vec![
"zamm_yin::node_wrappers::BaseNodeTrait".to_owned(),
"zamm_yin::graph::value_wrappers::StrongValue".to_owned(),
"zamm_yin::graph::value_wrappers::unwrap_value".to_owned(),
"std::rc::Rc".to_owned(),
],
atom: formatdoc! {r#"
impl {name} {{
/// Set {boxed_primitive} value for this concept.
pub fn set_value(&mut self, value: {unboxed_primitive}) {{
self.essence_mut()
.set_value(Rc::new({strongvalue_init}));
}}
/// Retrieve {boxed_primitive}-valued StrongValue.
#[allow(clippy::rc_buffer)]
pub fn value(&self) -> Option<Rc<{boxed_primitive}>> {{
unwrap_value::<{boxed_primitive}>(self.essence().value())
}}
}}"#, name = cfg.tao_cfg.this.name,
unboxed_primitive = cfg.rust_primitive_unboxed_name,
boxed_primitive = cfg.rust_primitive_boxed_name,
strongvalue_init = strongvalue_init,
},
}
}
fn data_concept_test_fragment(cfg: &DataFormatConfig) -> AtomicFragment {
AtomicFragment {
imports: vec![],
atom: formatdoc! {r#"
#[test]
fn get_value_none() {{
initialize_kb();
let concept = {name}::new();
assert_eq!(concept.value(), None);
}}
#[test]
fn get_value_some() {{
initialize_kb();
let mut concept = {name}::new();
concept.set_value({sample_value});
assert_eq!(concept.value(), Some(Rc::from({sample_value})));
}}"#, name = cfg.tao_cfg.this.name,
sample_value = cfg.default_value,
},
}
}
pub fn add_data_fragments(cfg: &DataFormatConfig, file: &mut FileFragment) {
file.append(Rc::new(RefCell::new(data_concept_fragment(cfg))));
file.append_test(Rc::new(RefCell::new(data_concept_test_fragment(cfg))));
}
#[cfg(test)]
mod tests {
use super::*;
use std::rc::Rc;
#[test]
fn test_string_output() {
let mut f = FileFragment::new();
add_data_fragments(
&DataFormatConfig {
rust_primitive_unboxed_name: Rc::from("String"),
rust_primitive_boxed_name: Rc::from("String"),
..DataFormatConfig::default()
},
&mut f,
);
let code = f.generate_code();
assert!(code.contains("String"));
assert!(!code.contains("i64"));
assert!(code.contains("set_value"));
}
#[test]
fn test_int_output() {
let mut f = FileFragment::new();
add_data_fragments(
&DataFormatConfig {
rust_primitive_unboxed_name: Rc::from("i64"),
rust_primitive_boxed_name: Rc::from("i64"),
..DataFormatConfig::default()
},
&mut f,
);
let code = f.generate_code();
assert!(code.contains("i64"));
assert!(code.contains("set_value"));
}
}