ninja_files_data2/rule/
builder.rs

1use std::collections::BTreeMap;
2
3use crate::{
4    Command, CommandBuilder, CommandBuilderError, InvalidVariable, InvalidVariableId, Rule,
5    Variable, VariableId,
6};
7
8pub struct RuleBuilder {
9    command: Option<Command>,
10    shadow: BTreeMap<VariableId, Variable>,
11    generator: bool,
12    errors: Vec<RuleBuilderError>,
13}
14
15#[derive(Clone, Debug)]
16pub enum RuleBuilderError {
17    InvalidCommand(Vec<CommandBuilderError>),
18    InvalidVariableId(InvalidVariableId),
19    InvalidVariable(InvalidVariable),
20    VariableAlreadyDefined {
21        id: VariableId,
22        previous: Variable,
23        var: Variable,
24    },
25}
26
27impl RuleBuilder {
28    pub fn new<C>(command_builder: C) -> Self
29    where
30        C: Into<CommandBuilder>,
31    {
32        let mut command = None;
33        let mut errors = vec![];
34        match command_builder.into().build() {
35            Ok(com) => command = Some(com),
36            Err(err) => errors.push(RuleBuilderError::InvalidCommand(err)),
37        };
38        RuleBuilder {
39            command,
40            shadow: BTreeMap::new(),
41            generator: false,
42            errors,
43        }
44    }
45
46    pub fn build(&self) -> Result<Rule, Vec<RuleBuilderError>> {
47        let errors = self.errors.clone();
48        let shadow = self.shadow.clone();
49        let generator = self.generator;
50
51        if !self.errors.is_empty() {
52            return Err(errors);
53        }
54
55        //should be safe, as it should be an err thus early return
56        let command = self.command.clone().unwrap();
57
58        let rule = Rule {
59            command,
60            shadow,
61            generator,
62        };
63        Ok(rule)
64    }
65
66    pub fn generator(mut self, generator: bool) -> Self {
67        self.generator = generator;
68        self
69    }
70
71    pub fn variable<Id, Var>(mut self, id: Id, var: Var) -> Self
72    where
73        Id: AsRef<str>,
74        Var: AsRef<str>,
75    {
76        let id = VariableId::try_create(id);
77        let var = Variable::try_create(var);
78        match (id, var) {
79            (Ok(id), Ok(var)) => match self.shadow.insert(id.clone(), var.clone()) {
80                Some(previous) if var == previous => (),
81                Some(previous) => {
82                    self.errors
83                        .push(RuleBuilderError::VariableAlreadyDefined { id, previous, var })
84                }
85                None => (),
86            },
87            (Ok(_), Err(v)) => self.errors.push(RuleBuilderError::InvalidVariable(v)),
88            (Err(i), Ok(_)) => self.errors.push(RuleBuilderError::InvalidVariableId(i)),
89            (Err(i), Err(v)) => {
90                self.errors.push(RuleBuilderError::InvalidVariable(v));
91                self.errors.push(RuleBuilderError::InvalidVariableId(i));
92            }
93        }
94        self
95    }
96}
97
98impl From<Rule> for RuleBuilder {
99    fn from(value: Rule) -> Self {
100        let mut builder = RuleBuilder::new(value.command).generator(value.generator);
101        for (id, var) in value.shadow.into_iter() {
102            builder = builder.variable(id, var);
103        }
104        builder
105    }
106}