diff options
| author | troido <troido@protonmail.com> | 2020-02-06 01:06:27 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-02-06 01:06:27 +0100 |
| commit | 283c5287b2dd7b4b83e51756bd7c41d5a3c35ef9 (patch) | |
| tree | e6990af51b4827fc648676ff2b03804890438728 | |
| parent | 7a4de27a97dc1e3cc2e517d96683e3c4ba9f7508 (diff) | |
always include type for arguments
| -rw-r--r-- | src/compwrapper.rs | 110 |
1 files changed, 74 insertions, 36 deletions
diff --git a/src/compwrapper.rs b/src/compwrapper.rs index 35986ce..4a861db 100644 --- a/src/compwrapper.rs +++ b/src/compwrapper.rs @@ -135,7 +135,7 @@ impl Parameter { } } -#[derive(Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ParamType { String, // Pos, @@ -157,22 +157,23 @@ impl ParamType { #[derive(Debug, PartialEq)] pub struct Template { - pub arguments: Vec<(String, Option<Parameter>)>, + pub arguments: Vec<(String, ParamType, Option<Parameter>)>, pub components: Vec<(ComponentType, HashMap<String, CompParam>)> } impl Template { pub fn from_json(val: Value) -> Result<Template, &'static str>{ - let mut arguments: Vec<(String, Option<Parameter>)> = Vec::new(); - for arg in val.get("arguments").ok_or("property 'arguments' not found")?.as_array().ok_or("arguments is not a json object")? { + let mut arguments: Vec<(String, ParamType, Option<Parameter>)> = Vec::new(); + for arg in val.get("arguments").ok_or("property 'arguments' not found")?.as_array().ok_or("arguments is not an array")? { let tup = arg.as_array().ok_or("argument is not an array")?; - let key = tup.get(0).ok_or("argument has no index name")?.as_str().ok_or("argument name is not a string")?.to_string(); - let value = tup.get(1).ok_or("argument has only name")?; - if value.is_null() { - arguments.push((key.clone(), None)); + let key = tup.get(0).ok_or("argument has no name")?.as_str().ok_or("argument name is not a string")?.to_string(); + let typ = ParamType::from_str(tup.get(1).ok_or("argument has no type")?.as_str().ok_or("argument type not a string")?).ok_or("failed to parse argument type")?; + let def = tup.get(2).ok_or("argument has no default")?; + if def.is_null() { + arguments.push((key.clone(), typ, None)); } else { - arguments.push((key.clone(), Some(Parameter::from_json(value).ok_or("invalid argument default")?))); + arguments.push((key.clone(), typ, Some(Parameter::from_typed_json(typ, def).ok_or("invalid argument default")?))); } } let mut components = Vec::new(); @@ -191,16 +192,11 @@ impl Template { )), "A" => { let argname = paramvalue.as_str().ok_or("argument parameter not a string")?.to_string(); - let arg = arguments.iter().find(|(a, d)| a == &argname).ok_or("unknown argument name")?; - match &arg.1 { - Some(param) => { - if param.paramtype() == paramtype { - Ok(CompParam::Argument(argname)) - } else { - Err("wrong argument type") - } - }, - None => Ok(CompParam::Argument(argname)) + let arg = arguments.iter().find(|(a, t, d)| a == &argname).ok_or("unknown argument name")?; + if arg.1 == paramtype { + Ok(CompParam::Argument(argname)) + } else { + Err("wrong argument type") } }, _ => Err("unknown compparam type") @@ -215,35 +211,33 @@ impl Template { }) } - pub fn instantiate(&self, args: Vec<Parameter>, kwargs: HashMap<String, Parameter>) -> Option<Vec<CompWrapper>>{ + pub fn instantiate(&self, args: Vec<Parameter>, kwargs: HashMap<String, Parameter>) -> Result<Vec<CompWrapper>, &str>{ let mut components: Vec<CompWrapper> = Vec::new(); for (comptype, compparams) in &self.components { let mut compargs: HashMap<&str, &Parameter> = HashMap::new(); for (name, param) in compparams { match param { - CompParam::Constant(val) => {compargs.insert(name.as_str(), &val); Some(())}, + CompParam::Constant(val) => {compargs.insert(name.as_str(), &val); Ok(())}, CompParam::Argument(argname) => { if let Some(argval) = kwargs.get(argname.as_str()) { compargs.insert(name.as_str(), argval); - Some(()) - } else if let Some(idx) = self.arguments.iter().position(|(x, d)| x == name){ + Ok(()) + } else if let Some(idx) = self.arguments.iter().position(|(x, t, d)| x == name){ if idx < args.len() { compargs.insert(name.as_str(), &args[idx]); - Some(()) + Ok(()) } else { - println!("positional argument out of range"); - None + Err("positional argument out of range") } } else { - println!("can't find parameter value, comptype: {:?}, name: {}, argname: {}", comptype, name, argname); - None + Err("can't find parameter value") } } }?; } - components.push(CompWrapper::load_component(*comptype, compargs)?); + components.push(CompWrapper::load_component(*comptype, compargs).ok_or("failed to load component")?); } - Some(components) + Ok(components) } } @@ -280,7 +274,7 @@ mod tests { fn grass_from_json(){ let result = Template::from_json(json!({ "arguments": [ - ["sprite", ["string", "grass1"]] + ["sprite", "string", "grass1"] ], "components": [ ["Visible", { @@ -290,7 +284,7 @@ mod tests { ] })).unwrap(); let constructed = Template{ - arguments: vec![("sprite".to_string(), Some(Parameter::String("grass1".to_string())))], + arguments: vec![("sprite".to_string(), ParamType::String, Some(Parameter::String("grass1".to_string())))], components: vec![ (ComponentType::Visible, hashmap!( "sprite".to_string() => CompParam::Argument("sprite".to_string()), @@ -305,7 +299,7 @@ mod tests { fn invalid_component_name(){ let result = Template::from_json(json!({ "arguments": [ - ["sprite", ["string", "grass1"]] + ["sprite", "string", null] ], "components": [ ["visible", { // no capital so invalid @@ -323,7 +317,7 @@ mod tests { fn invalid_parameter_type(){ let result = Template::from_json(json!({ "arguments": [ - ["sprite", ["string", "grass1"]] + ["sprite", "string", "grass1"] ], "components": [ ["Visible", { @@ -339,7 +333,7 @@ mod tests { fn unknown_argument_name(){ let result = Template::from_json(json!({ "arguments": [ - ["sprite", ["string", "grass1"]] + ["sprite", "string", "grass1"] ], "components": [ ["Visible", { @@ -355,7 +349,7 @@ mod tests { fn wrong_argument_type(){ let result = Template::from_json(json!({ "arguments": [ - ["sprite", ["int", 1]] + ["sprite", "int", 1] ], "components": [ ["Visible", { @@ -366,6 +360,50 @@ mod tests { })).unwrap_err(); assert_eq!(result, "wrong argument type"); } + + + + #[test] + fn wrong_argument_default(){ + let result = Template::from_json(json!({ + "arguments": [ + ["sprite", "string", 1] + ], + "components": [ + ["Visible", { + "sprite": ["A", "sprits"], + "height": ["C", 0.1] + }] + ] + })).unwrap_err(); + assert_eq!(result, "invalid argument default"); + } + + + #[test] + fn null_argument(){ + let result = Template::from_json(json!({ + "arguments": [ + ["sprite", "string", null] + ], + "components": [ + ["Visible", { + "sprite": ["A", "sprite"], + "height": ["C", 0.1] + }] + ] + })).unwrap(); + let constructed = Template{ + arguments: vec![("sprite".to_string(), ParamType::String, None)], + components: vec![ + (ComponentType::Visible, hashmap!( + "sprite".to_string() => CompParam::Argument("sprite".to_string()), + "height".to_string() => CompParam::Constant(Parameter::Float(0.1)) + )) + ] + }; + assert_eq!(result, constructed); + } } |
