From 70db58f688f0dbdd69231da570cf8dbb54e5ca81 Mon Sep 17 00:00:00 2001 From: troido Date: Fri, 7 Feb 2020 14:08:18 +0100 Subject: named stuff properly; added encyclopedia and template --- src/template.rs | 267 +++----------------------------------------------------- 1 file changed, 12 insertions(+), 255 deletions(-) (limited to 'src/template.rs') diff --git a/src/template.rs b/src/template.rs index bdf86b3..51bba8b 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,266 +1,23 @@ + use std::collections::HashMap; -use serde_json::Value; -use super::componentparameter::ComponentParameter; -use super::parameter::{Parameter, ParameterType}; -use super::componentwrapper::{ComponentWrapper, ComponentType}; +use crate::parameter::Parameter; -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub struct Template { - pub arguments: Vec<(String, ParameterType, Option)>, - pub components: Vec<(ComponentType, HashMap)> + pub name: String, + pub args: Vec, + pub kwargs: HashMap } -impl Template { - - fn parse_definition_arguments(args: &Value) -> Result)>, &'static str> { - let mut arguments: Vec<(String, ParameterType, Option)> = Vec::new(); - for arg in args.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 name")?.as_str().ok_or("argument name is not a string")?.to_string(); - let typ = ParameterType::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(), typ, Some(Parameter::from_typed_json(typ, def).ok_or("invalid argument default")?))); - } - } - Ok(arguments) - } - - fn parse_definition_components(comps: &Value) -> Result)>, &'static str> { - let mut components = Vec::new(); - for tup in comps.as_array().ok_or("components is not a json array")? { - let comptype = ComponentType::from_str(tup - .get(0).ok_or("index 0 not in component")? - .as_str().ok_or("component name not a string")? - ).ok_or("not a valid componenttype")?; - let mut parameters: HashMap = HashMap::new(); - for (key, value) in tup.get(1).ok_or("index 1 not in component")?.as_object().ok_or("component parameters not a json object")? { - let param = ComponentParameter::from_json(value)?; - parameters.insert(key.clone(), param); - } - components.push((comptype, parameters)); - } - Ok(components) - } - - fn validate(&self) -> Result<(), &'static str> { - for (comptype, parameters) in &self.components { - for (paramname, paramtype) in comptype.parameters() { - let param = parameters.get(paramname).ok_or("missing parameter")?; - let actualtype = param.get_type(&self.arguments)?; - if actualtype != paramtype { - return Err("parameter type incorrect"); - } - } - } - Ok(()) - } - - pub fn from_json(val: &Value) -> Result{ - let template = Template { - arguments: Self::parse_definition_arguments(val.get("arguments").ok_or("property 'arguments' not found")?)?, - components: Self::parse_definition_components(val.get("components").ok_or("property 'components' not found")?)? - }; - template.validate()?; - Ok(template) - } +impl Template { - fn prepare_arguments(&self, args: Vec, kwargs: HashMap) -> Result, &str> { - let mut arguments: HashMap<&str, Parameter> = HashMap::new(); - for (idx, (name, typ, def)) in self.arguments.iter().enumerate() { - let value: Option = { - if let Some(val) = kwargs.get(name) { - Some(val.clone()) - } else if let Some(val) = args.get(idx) { - Some(val.clone()) - } else if let Some(val) = def { - Some(val.clone()) - } else { - None - } - }; - let param = value.ok_or("argument has no value")?; - if param.paramtype() != *typ { - return Err("argument has incorrect type"); - } - arguments.insert(name, param); - } - Ok(arguments) - } - - pub fn instantiate(&self, args: Vec, kwargs: HashMap) -> Result, &str>{ - let mut components: Vec = Vec::new(); - let arguments = self.prepare_arguments(args, kwargs)?; - for (comptype, compparams) in &self.components { - let mut compargs: HashMap<&str, Parameter> = HashMap::new(); - for (name, param) in compparams { - compargs.insert(name.as_str(), param.evaluate(&arguments).ok_or("argument not found")?); - } - components.push(ComponentWrapper::load_component(*comptype, compargs).ok_or("failed to load component")?); + pub fn empty(name: &str) -> Self { + Self { + name: name.to_string(), + args: Vec::new(), + kwargs: HashMap::new() } - Ok(components) - } -} - - - -#[cfg(test)] -mod tests { - use super::*; - use crate::hashmap; - use serde_json::json; - - - #[test] - fn empty_template_from_json() { - assert_eq!( - Template::from_json(&json!({ - "arguments": [], - "components": [] - })).unwrap(), - Template{ - arguments: vec![], - components: vec![] - } - ); - } - - #[test] - fn grass_from_json(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "string", "grass1"] - ], - "components": [ - ["Visible", { - "sprite": ["A", "sprite"], - "height": ["float", 0.1] - }] - ] - })).unwrap(); - let constructed = Template{ - arguments: vec![("sprite".to_string(), ParameterType::String, Some(Parameter::String("grass1".to_string())))], - components: vec![ - (ComponentType::Visible, hashmap!( - "sprite".to_string() => ComponentParameter::Argument("sprite".to_string()), - "height".to_string() => ComponentParameter::Constant(Parameter::Float(0.1)) - )) - ] - }; - assert_eq!(result, constructed); - } - - #[test] - fn invalid_component_name(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "string", null] - ], - "components": [ - ["visible", { // no capital so invalid - "sprite": ["A", "sprite"], - "height": ["float", 0.1] - }] - ] - })).unwrap_err(); - assert_eq!(result, "not a valid componenttype"); - } - - - - #[test] - fn invalid_parameter_type(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "string", "grass1"] - ], - "components": [ - ["Visible", { - "sprite": ["A", "sprite"], - "height": ["string", "0.1"] - }] - ] - })).unwrap_err(); - assert_eq!(result, "parameter type incorrect"); - } - - #[test] - fn unknown_argument_name(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "string", "grass1"] - ], - "components": [ - ["Visible", { - "sprite": ["A", "sprits"], - "height": ["float", 0.1] - }] - ] - })).unwrap_err(); - assert_eq!(result, "unknown argument name"); - } - - #[test] - fn wrong_argument_type(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "int", 1] - ], - "components": [ - ["Visible", { - "sprite": ["A", "sprite"], - "height": ["float", 0.1] - }] - ] - })).unwrap_err(); - assert_eq!(result, "parameter type incorrect"); - } - - - - #[test] - fn wrong_argument_default(){ - let result = Template::from_json(&json!({ - "arguments": [ - ["sprite", "string", 1] - ], - "components": [ - ["Visible", { - "sprite": ["A", "sprits"], - "height": ["float", 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": ["float", 0.1] - }] - ] - })).unwrap(); - let constructed = Template{ - arguments: vec![("sprite".to_string(), ParameterType::String, None)], - components: vec![ - (ComponentType::Visible, hashmap!( - "sprite".to_string() => ComponentParameter::Argument("sprite".to_string()), - "height".to_string() => ComponentParameter::Constant(Parameter::Float(0.1)) - )) - ] - }; - assert_eq!(result, constructed); } } -- cgit