use hocon_rs::Value;
use crate::collision_kind::CollisionKind;
use crate::lc_action::LcAction;
use crate::lc_entity_type::LcEntityType;
use crate::lc_single_action_config::{LcSingleActionConfig, LcConfigRaw};
use crate::parser::collision_kind_parser::parse_collision_kind;
pub fn parse_lc_config_raw(value: &Value) -> Result<LcConfigRaw, String> {
if let Value::Object(map) = value {
if let (Some(lca_value), Some(collision_value)) = (map.get("lca"), map.get("collision")) {
let collision = parse_collision_kind(collision_value)?;
return Ok(LcConfigRaw {
effect_value: lca_value.clone(),
collision,
});
}
if map.contains_key("lca") && !map.contains_key("collision") {
return Err("LcaConfig requires 'collision' field".to_string());
}
if map.contains_key("collision") && !map.contains_key("lca") {
return Err("LcaConfig requires 'lca' field".to_string());
}
return Ok(LcConfigRaw {
effect_value: value.clone(),
collision: CollisionKind::OTHER,
});
}
Err(format!(
"LcaConfig parser expects an object, got: {:?}",
value
))
}
pub fn parse_lc_config<T, F>(
value: &Value,
parse_effect: &F,
) -> Result<LcSingleActionConfig<T>, String>
where
T: LcEntityType,
F: Fn(&Value) -> Result<Box<dyn LcAction<T>>, String>,
{
let raw = parse_lc_config_raw(value)?;
let effect = parse_effect(&raw.effect_value)?;
Ok(LcSingleActionConfig {
action: effect,
collision: raw.collision,
})
}
#[cfg(test)]
mod tests {
use super::*;
use hocon_rs::Config;
#[test]
fn test_parse_simple_format_raw() {
let hocon_str = r#"{ DealDamage: 10 }"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value).unwrap();
assert_eq!(result.collision, CollisionKind::OTHER);
assert!(
result
.effect_value
.as_object()
.unwrap()
.contains_key("DealDamage")
);
}
#[test]
fn test_parse_full_format_self() {
let hocon_str = r#"
{
lca: { DealDamage: 25 }
collision: "Self"
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value).unwrap();
assert_eq!(result.collision, CollisionKind::SELF);
}
#[test]
fn test_parse_full_format_same_kind() {
let hocon_str = r#"
{
lca: { DealDamage: 15 }
collision: "SameKind"
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value).unwrap();
assert_eq!(result.collision, CollisionKind::SAME_KIND);
}
#[test]
fn test_parse_full_format_other() {
let hocon_str = r#"
{
lca: { DealDamage: 5 }
collision: "Other"
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value).unwrap();
assert_eq!(result.collision, CollisionKind::OTHER);
}
#[test]
fn test_parse_full_unquoted_collision() {
let hocon_str = r#"
{
lca: { DealDamage: 5 }
collision: Self
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value).unwrap();
assert_eq!(result.collision, CollisionKind::SELF);
}
#[test]
fn test_parse_missing_lca_field() {
let hocon_str = r#"
{
collision: "Self"
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value);
assert!(result.is_err());
if let Err(err) = result {
assert!(err.contains("requires 'lca' field"));
}
}
#[test]
fn test_parse_missing_collision_field() {
let hocon_str = r#"
{
lca: { DealDamage: 10 }
}
"#;
let value: Value = Config::parse_str(hocon_str, None).unwrap();
let result = parse_lc_config_raw(&value);
assert!(result.is_err());
if let Err(err) = result {
assert!(err.contains("requires 'collision' field"));
}
}
#[test]
fn test_parse_not_an_object() {
let hocon_str = r#"value = 42"#;
let parsed: Value = Config::parse_str(hocon_str, None).unwrap();
let value = parsed.as_object().unwrap().get("value").unwrap();
let result = parse_lc_config_raw(value);
assert!(result.is_err());
if let Err(err) = result {
assert!(err.contains("expects an object"));
}
}
}