1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
use serde_json::Value;
use std::collections::HashMap;
use crate::node::*;
use crate::workers::Workers;

#[allow(dead_code)]
pub struct Engine {
  id: String,
  workers: Workers,
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum Error {
  VersionMismatch,
}

#[allow(dead_code)]
impl <'a, 'b> Engine {
  pub fn new(id: &str, workers: Workers) -> Engine {
    Engine {
      id: id.to_string(),
      workers: workers,
    }
  }

  pub fn parse_json(&self, json: &str) -> Result<HashMap<i64, Node>, Error> {
    let value: Value = serde_json::from_str(json).unwrap();
    self.parse_value(value)
  }

  pub fn parse_value(&self, value: Value) -> Result<HashMap<i64, Node>, Error> {
    let version = value["id"].as_str().unwrap().to_string();
    if self.id != version {
      return Err(Error::VersionMismatch);
    }
    let nodess: HashMap<String, Node> = serde_json::from_value(value["nodes"].clone()).unwrap();
    Ok(nodess.into_iter().map(|(k,v)| (k.parse::<i64>().unwrap(), v)).collect())
  }

  pub fn process(&self, nodes: &HashMap<i64, Node>, start_node_id: i64) -> Result<OutputData, Error> {
    let mut cache: HashMap<i64, OutputData> = HashMap::new();
    let mut closed_nodes: Vec<i64> = Vec::new();
    let end_id = self.process_nodes(&nodes[&start_node_id], &nodes, &mut cache, &mut closed_nodes);
    Ok(cache[&end_id].clone())
  }

  fn process_node(&self, node: &'_ Node, nodes: &HashMap<i64, Node>, cache: &mut HashMap<i64, OutputData>, closed_nodes: &mut Vec<i64>) -> OutputData {
    if cache.contains_key(&node.id) {
      return cache[&node.id].clone();
    }

    let mut input_data = InputData::new();
    for (name, input) in &node.inputs {
      for conn in &input.connections {
        let out = self.process_node(&nodes[&conn.node], nodes, cache, closed_nodes);
        input_data.insert(name.clone(), out);
      }
    }
    let output = self.workers.call(&node.name, node.clone(), input_data).unwrap();
    cache.insert(node.id, output.clone());
    return output;
  }

  fn process_nodes(&self, node: &'_ Node, nodes: &HashMap<i64, Node>, cache: &mut HashMap<i64, OutputData>, closed_nodes: &mut Vec<i64>) -> i64 {
    let mut id: i64 = node.id;
    if !closed_nodes.contains(&node.id) {
      let outputdata = self.process_node(&node, &nodes, cache, closed_nodes);
      for (name, output) in &node.outputs {
        if outputdata.contains_key(name) {
          for connection in &output.connections {
            if !closed_nodes.contains(&connection.node) {
              id = self.process_nodes(&nodes[&connection.node], &nodes, cache, closed_nodes);
            }
          }
        } else {
          if name == "true" || name == "false" {
            for connection in &output.connections {
              self.disable_node_tree(&nodes[&connection.node], nodes, closed_nodes);
            }
          }
        }
      }
    }
    id
  }

  fn disable_node_tree(&self, node: &'_ Node, nodes: &HashMap<i64, Node>, closed_nodes: &mut Vec<i64>) {
    match node.inputs.get("action") {
      None => (),
      Some(input) => {
        if input.connections.len() == 1 {
          closed_nodes.push(node.id);
          for (_, output) in node.outputs.clone().into_iter().filter(|(name, _)| name == "action" || name == "true" || name == "false") {
            for connection in &output.connections {
              self.disable_node_tree(&nodes[&connection.node], nodes, closed_nodes);
            }
          }
        }
      },
    }
  }
}