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
use super::super::parser::ast::Expression;
use super::super::transformers::kinds::boolean_transform::BooleanTransform;
use super::super::transformers::kinds::number_transform::NumberTransform;
use super::super::transformers::kinds::string_transform::StringTransform;
use super::super::transformers::parser::Parser;
use super::super::transformers::transformer_list::TransformerList;
use super::super::transformers::value_types::ValueType;
use super::to_custom_transformers::ToCustomTransformers;
use super::{super::envuse::to_envs::ToEnvs, display_program_error::display_program_error};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

/// The program is a structure content the filename and the source
#[derive(Debug, Serialize, Deserialize)]
pub struct Program {
    pub location: Option<String>,
    pub source: String,
    pub ast: Expression,
}

impl Program {
    pub fn parse<T, D>(
        &self,
        values: T,
        custom_transformers: D,
    ) -> Result<BTreeMap<String, ValueType>, Box<dyn std::error::Error>>
    where
        T: ToEnvs,
        D: ToCustomTransformers,
    {
        display_program_error(
            self.parse_unwrap(values, custom_transformers),
            self.source.clone(),
            self.location.clone(),
        )
    }

    fn parse_unwrap<T, D>(
        &self,
        values: T,
        custom_transformers: D,
    ) -> Result<BTreeMap<String, ValueType>, Box<dyn std::error::Error>>
    where
        T: ToEnvs,
        D: ToCustomTransformers,
    {
        let mut transformer_list: TransformerList = Default::default();

        transformer_list.insert("unknown", Box::new(StringTransform));
        transformer_list.insert("str", Box::new(StringTransform));
        transformer_list.insert("string", Box::new(StringTransform));
        transformer_list.insert("number", Box::new(NumberTransform));
        transformer_list.insert("bool", Box::new(BooleanTransform));
        transformer_list.insert("boolean", Box::new(BooleanTransform));

        for key in custom_transformers.to_vec() {
            transformer_list.insert(key, Box::new(StringTransform));
        }

        let envs_values = values.to_envs();

        let document = &self
            .ast
            .as_document()
            .expect("AST Parser error, the ast expressions is not Expression::Document");

        let expressions = &document.elements;

        let mut configs: BTreeMap<String, ValueType> = BTreeMap::new();

        for expression in expressions {
            let variable = expression
                .as_variable()
                .expect("Expression is not supported");

            let value = Parser::to_parse_variable(&transformer_list, &variable, &envs_values)?;

            configs.insert(variable.name.to_string(), value);
        }

        Ok(configs)
    }
}