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
use std::collections::HashMap;
use tinyjson::JsonValue;
use stepflow::{Error, data::{BoolValue, TrueVar}, prelude::*};
use stepflow::object::{ObjectStore, IdError};
use stepflow::Session;
use stepflow::data::{StateData, VarId, StringVar, EmailVar, BoolVar};
use super::error::StepFlowParseError;
use crate::json::jsonval_get_obj;


pub fn parse_vars_json(session: &mut Session, vars_json: &HashMap<String, JsonValue>) -> Result<(), StepFlowParseError> {
  for (name, vartype) in vars_json {
      if let JsonValue::String(vartype) = vartype {
          let varid = session.var_store_mut().reserve_id();
          let var = match &vartype[..] {
              "String" => StringVar::new(varid).boxed(),
              "Email" => EmailVar::new(varid).boxed(),
              "Bool" => BoolVar::new(varid).boxed(),
              "True" => TrueVar::new(varid).boxed(),
              _ => return Err(StepFlowParseError::UnexpectedValue(vartype.clone()))
          };
          session.var_store_mut().register_named(name.clone(), var)
              .map_err(|e| stepflow::Error::VarId(e))?;
          
      } else {
          return Err(StepFlowParseError::WrongType { key: name.to_owned(), expected: "String".to_owned() })
      }
  }
  Ok(())
}

pub fn statedata_from_jsonval_obj(jsonval_obj: &HashMap<String, JsonValue>, varstore: &ObjectStore<Box<dyn Var + Send + Sync>, VarId>) -> Result<StateData, StepFlowParseError> {
    let mut statedata = StateData::new();   // FUTURE: pre-alloc this
    for (var_name,val_json) in jsonval_obj {
        let var = varstore.get_by_name(&var_name[..]).ok_or_else(|| StepFlowParseError::UnexpectedValue(var_name.clone()))?;
        let val = match val_json {
            JsonValue::String(val_str) => {
                var.value_from_str(&val_str[..]).map_err(|e| Error::InvalidValue(e))?
            },
            JsonValue::Boolean(val) => BoolValue::new(*val).boxed(),
            _ => return Err(StepFlowParseError::WrongType { key: var_name.clone(), expected: "String or Boolean".to_owned()}),
        };
        statedata.insert(var, val).map_err(|e| Error::InvalidValue(e))?;
      }
      Ok(statedata)
  }

pub fn parse_statedata_json(json: &str, varstore: &ObjectStore<Box<dyn Var + Send + Sync>, VarId>) -> Result<StateData, StepFlowParseError> {
  let parsed: JsonValue = json.parse()?;
  let statedata_json = jsonval_get_obj(&parsed, "root")?;
  let statedata = statedata_from_jsonval_obj(statedata_json, varstore)?;
  Ok(statedata)
}

pub fn json_value_from_val(val: &Box<dyn Value>) -> JsonValue {
  match val.get_baseval() {
      stepflow::data::BaseValue::String(s) => JsonValue::String(s),
      stepflow::data::BaseValue::Boolean(b) => JsonValue::Boolean(b),
      stepflow::data::BaseValue::Float(f) => JsonValue::Number(f),
  }
}

pub fn json_value_from_statedata(statedata: &StateData, varstore: &ObjectStore<Box<dyn Var + Send + Sync>, VarId>) -> Result<JsonValue, StepFlowParseError> {
    let mut result = HashMap::new();
    for (varid, val) in statedata.iter_val() {
        let name = varstore.name_from_id(varid)
            .ok_or_else(|| stepflow::Error::VarId(IdError::IdHasNoName(varid.clone())))?
            .to_owned();
        let val = json_value_from_val(val);
        result.insert(name, val);
    }
    Ok(JsonValue::Object(result))
}