diff options
| author | troido <troido@protonmail.com> | 2020-02-07 14:08:18 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-02-07 14:08:18 +0100 |
| commit | 70db58f688f0dbdd69231da570cf8dbb54e5ca81 (patch) | |
| tree | ab8d61357f17ebd30c15e7206dde110da0fd1579 /src/template.rs | |
| parent | 45ed2cd201c79fae1c61a4f6f2982a9f5cfbceca (diff) | |
named stuff properly; added encyclopedia and template
Diffstat (limited to 'src/template.rs')
| -rw-r--r-- | src/template.rs | 267 |
1 files changed, 12 insertions, 255 deletions
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<Parameter>)>, - pub components: Vec<(ComponentType, HashMap<String, ComponentParameter>)> + pub name: String, + pub args: Vec<Parameter>, + pub kwargs: HashMap<String, Parameter> } -impl Template { - - fn parse_definition_arguments(args: &Value) -> Result<Vec<(String, ParameterType, Option<Parameter>)>, &'static str> { - let mut arguments: Vec<(String, ParameterType, Option<Parameter>)> = 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<Vec<(ComponentType, HashMap<String, ComponentParameter>)>, &'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<String, ComponentParameter> = 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<Template, &'static str>{ - 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<Parameter>, kwargs: HashMap<String, Parameter>) -> Result<HashMap<&str, Parameter>, &str> { - let mut arguments: HashMap<&str, Parameter> = HashMap::new(); - for (idx, (name, typ, def)) in self.arguments.iter().enumerate() { - let value: Option<Parameter> = { - 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<Parameter>, kwargs: HashMap<String, Parameter>) -> Result<Vec<ComponentWrapper>, &str>{ - let mut components: Vec<ComponentWrapper> = 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); } } |
