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
//! Parsing utilities for JSON config files. (Requires the `json-parsing` feature.)

use std::path::Path;

use failure::Error;
use serde_json::{ self, Value };

use { RawValue, RawStructValue };


/// Parse a RawStructValue from some JSON.
///
/// This can then be used to generate a config struct using `create_config_module` or
/// `write_config_module`.
pub fn parse_config<S: AsRef<str>>(config_source: S) -> Result<RawStructValue, Error>
{
    use parsing::{ self, ParsedConfig };

    let json_object: ParsedConfig<Value> = serde_json::from_str(config_source.as_ref())?;

    let raw_config = parsing::parsed_to_raw_config(json_object, json_to_raw_value);

    Ok(raw_config)
}


/// Parse a RawStructValue from a JSON file.
///
/// This can then be used to generate a config struct using `create_config_module` or
/// `write_config_module`.
pub fn parse_config_from_file<P: AsRef<Path>>(config_path: P) -> Result<RawStructValue, Error>
{
    use parsing;

    let config_source = parsing::slurp_file(config_path.as_ref())?;

    parse_config(&config_source)
}


fn json_to_raw_value(super_struct: &str, super_key: &str, value: Value) -> RawValue
{
    match value
    {
        Value::Null => RawValue::Option(None),
        Value::Bool(value) => RawValue::Bool(value),
        Value::Number(value) => match (value.as_i64(), value.as_u64(), value.as_f64())
        {
            (Some(x), _, _) => RawValue::I64(x),
            (None, Some(x), _) => RawValue::U64(x),
            (None, None, Some(x)) => RawValue::F64(x),
            _ => unimplemented!("Should handle error here")
        },
        Value::String(value) => RawValue::String(value),
        Value::Array(values) => {
            RawValue::Array(values.into_iter()
                .map(|value| json_to_raw_value(super_struct, super_key, value))
                .collect())
        },
        Value::Object(values) => {
            let sub_struct_name = format!("{}__{}", super_struct, super_key);
            let values = values.into_iter()
                .map(
                    |(key, value)|
                    {
                        let value = json_to_raw_value(&sub_struct_name, &key, value);
                        (key, value)
                    })
                .collect();
            RawValue::Struct(RawStructValue { struct_name: sub_struct_name, fields: values })
        }
    }
}