summaryrefslogtreecommitdiff
path: root/src/template.rs
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-02-07 14:08:18 +0100
committertroido <troido@protonmail.com>2020-02-07 14:08:18 +0100
commit70db58f688f0dbdd69231da570cf8dbb54e5ca81 (patch)
treeab8d61357f17ebd30c15e7206dde110da0fd1579 /src/template.rs
parent45ed2cd201c79fae1c61a4f6f2982a9f5cfbceca (diff)
named stuff properly; added encyclopedia and template
Diffstat (limited to 'src/template.rs')
-rw-r--r--src/template.rs267
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);
}
}