ydevlib/
yocto.rs

1#[allow(unused)]
2use {
3    anyhow::{Context, Error, Result},
4    jlogger::{jdebug, jerror, jinfo, JloggerBuilder},
5    log::{debug, info, warn},
6    regex::Regex,
7    std::{
8        collections::HashMap,
9        fmt::Display,
10        fs,
11        path::{Path, PathBuf},
12    },
13};
14
15pub enum YoctoVarName {
16    Name(String),
17    NameValAppend(String),
18    NameValRemove(String),
19    NameFlag((String, String)),
20    NameOverride((String, String)),
21    NameOverrideAppend((String, String)),
22    NameOverrideRemove((String, String)),
23    NameAppendOverride((String, String)),
24    NameRemoveOverride((String, String)),
25    InvalidName,
26}
27
28pub enum YoctoVarType {
29    Value,
30    Override(String),
31    Flag(String),
32}
33
34pub struct YoctoVar {
35    name: String,
36    value: String,
37    ovalue: HashMap<String, String>,
38    fvalue: HashMap<String, String>,
39    default: String,
40}
41
42impl YoctoVar {
43    pub fn valid_varable_name(name: &str) -> bool {
44        Regex::new(r"^[A-Z][(A-Z)|(0-9)|_]*$")
45            .unwrap()
46            .is_match(name)
47    }
48
49    pub fn valid_override(s: &str) -> bool {
50        Regex::new(r"^[a-z]([a-z|0-9|-])*$").unwrap().is_match(s)
51    }
52
53    pub fn fix_str(s: &str) -> String {
54        s.trim()
55            .trim_start_matches("\"")
56            .trim_end_matches("\"")
57            .trim()
58            .to_string()
59    }
60
61    pub fn new(statement: Option<&str>) -> Result<Self> {
62        let name = statement
63            .map(|a| YoctoVar::fix_str(a))
64            .unwrap_or_else(|| String::from("UNDEFINE"));
65
66        if !YoctoVar::valid_varable_name(&name) {
67            return Err(Error::msg(format!("Invalid name {}", name)));
68        }
69
70        let n = YoctoVar {
71            name,
72            value: String::new(),
73            default: String::new(),
74            ovalue: HashMap::<String, String>::new(),
75            fvalue: HashMap::<String, String>::new(),
76        };
77
78        Ok(n)
79    }
80
81    pub fn new_default(name: &str, val: &str) -> Result<Self> {
82        let name = YoctoVar::fix_str(name);
83        let err_name = Error::msg(format!("Invalid name {}", name));
84
85        if !YoctoVar::valid_varable_name(&name) {
86            return Err(err_name);
87        }
88
89        Ok(YoctoVar {
90            name,
91            value: String::new(),
92            default: YoctoVar::fix_str(val),
93            ovalue: HashMap::<String, String>::new(),
94            fvalue: HashMap::<String, String>::new(),
95        })
96    }
97
98    pub fn set_default_value(&mut self, val: &str) {
99        self.default = YoctoVar::fix_str(val);
100    }
101
102    pub fn get_default_value(&self) -> &str {
103        self.default.as_str()
104    }
105
106    pub fn update(&mut self, statement: &str, value: &str) -> Result<()> {
107        let statement = YoctoVar::fix_str(statement);
108        let err_statement = Error::msg(format!("Invalid statement {}", statement));
109        let err_name = Error::msg(format!("Invalid name {} != {}", statement, self.name));
110        let val = value;
111
112        /* Only remove " XXX  " from v excluding "aaaXXXbbb" */
113        let var_remove = |v: &mut String, val: &str| {
114            if v.as_str() == val {
115                v.clear();
116            } else {
117                let val_fix_0 = format!(" {} ", val);
118                let val_fix_1 = format!("{} ", val);
119                let val_fix_2 = format!(" {}", val);
120                let mut nv = v.replace(&val_fix_0, "");
121                nv = nv.replace(&val_fix_1, "");
122                nv = nv.replace(&val_fix_2, "");
123                v.clear();
124                v.push_str(&nv);
125            }
126        };
127
128        match YoctoVar::parse_name(&statement) {
129            YoctoVarName::Name(n) => {
130                if self.name == "UNDEFINE" {
131                    self.name.clear();
132                    self.name.push_str(&n);
133                } else if n != self.name {
134                    return Err(err_name);
135                }
136                self.value.clear();
137                self.value.push_str(val);
138            }
139
140            YoctoVarName::NameValAppend(n) => {
141                if self.name == "UNDEFINE" {
142                    self.name.clear();
143                    self.name.push_str(&n);
144                } else if n != self.name {
145                    return Err(err_name);
146                }
147
148                self.value.push_str(val);
149            }
150
151            YoctoVarName::NameValRemove(n) => {
152                if self.name == "UNDEFINE" {
153                    self.name.clear();
154                    self.name.push_str(&n);
155                } else if n != self.name {
156                    return Err(err_name);
157                }
158
159                var_remove(&mut self.value, val);
160            }
161
162            YoctoVarName::NameFlag((n, f)) => {
163                if self.name == "UNDEFINE" {
164                    self.name.clear();
165                    self.name.push_str(&n);
166                } else if n != self.name {
167                    return Err(err_name);
168                }
169
170                let v = self.fvalue.entry(f).or_insert(String::new());
171                v.clear();
172                v.push_str(val);
173            }
174
175            YoctoVarName::NameOverride((n, o)) => {
176                if self.name == "UNDEFINE" {
177                    self.name.clear();
178                    self.name.push_str(&n);
179                } else if n != self.name {
180                    return Err(err_name);
181                }
182
183                let v = self.ovalue.entry(o).or_insert(String::new());
184                v.clear();
185                v.push_str(val);
186            }
187
188            YoctoVarName::NameOverrideAppend((n, o)) => {
189                if self.name == "UNDEFINE" {
190                    self.name.clear();
191                    self.name.push_str(&n);
192                } else if n != self.name {
193                    return Err(err_name);
194                }
195
196                let v = self.ovalue.entry(o).or_insert(String::new());
197                v.push_str(val);
198            }
199
200            YoctoVarName::NameOverrideRemove((n, o)) => {
201                if self.name == "UNDEFINE" {
202                    self.name.clear();
203                    self.name.push_str(&n);
204                } else if n != self.name {
205                    return Err(err_name);
206                }
207
208                let v = self.ovalue.entry(o).or_insert(String::new());
209                var_remove(v, val);
210            }
211
212            YoctoVarName::NameAppendOverride((n, o)) => {
213                if self.name == "UNDEFINE" {
214                    self.name.clear();
215                    self.name.push_str(&n);
216                } else if n != self.name {
217                    return Err(err_name);
218                }
219
220                let mut nvalue = self.value.clone();
221                nvalue.push_str(val);
222                let v = self.ovalue.entry(o).or_insert(String::new());
223                v.clear();
224                v.push_str(&nvalue);
225            }
226
227            YoctoVarName::NameRemoveOverride((n, o)) => {
228                if self.name == "UNDEFINE" {
229                    self.name.clear();
230                    self.name.push_str(&n);
231                } else if n != self.name {
232                    return Err(err_name);
233                }
234
235                let mut nvalue = self.value.clone();
236                var_remove(&mut nvalue, val);
237                let v = self.ovalue.entry(o).or_insert(String::new());
238                v.clear();
239                v.push_str(&nvalue);
240            }
241
242            _ => return Err(err_statement),
243        }
244
245        Ok(())
246    }
247
248    pub fn key_name<'a>(name: &'a str) -> Result<String> {
249        match YoctoVar::parse_name(name) {
250            YoctoVarName::Name(n) => Ok(n.to_string()),
251            YoctoVarName::NameValAppend(n) => Ok(n.to_string()),
252            YoctoVarName::NameValRemove(n) => Ok(n.to_string()),
253            YoctoVarName::NameFlag((n, _)) => Ok(n.to_string()),
254            YoctoVarName::NameOverride((n, _)) => Ok(n.to_string()),
255            YoctoVarName::NameOverrideAppend((n, _)) => Ok(n.to_string()),
256            YoctoVarName::NameOverrideRemove((n, _)) => Ok(n.to_string()),
257            YoctoVarName::NameAppendOverride((n, _)) => Ok(n.to_string()),
258            YoctoVarName::NameRemoveOverride((n, _)) => Ok(n.to_string()),
259            YoctoVarName::InvalidName => Err(Error::msg(format!("Invalid name {}", name))),
260        }
261    }
262
263    pub fn parse_name<'a>(name: &'a str) -> YoctoVarName {
264        let name = YoctoVar::fix_str(name);
265        let re =
266            Regex::new(r"([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)\[([a-z]([a-z|0-9|_]*[a-z|0-9])*)\]")
267                .unwrap();
268        if let Some(caps) = re.captures(&name) {
269            let n = caps.get(1).unwrap().as_str();
270            let f = caps.get(3).unwrap().as_str();
271            return YoctoVarName::NameFlag((String::from(n), String::from(f)));
272        }
273
274        let re = Regex::new(
275            r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)([:|_][a-z][1-9|a-z|-]*)([:|_][a-z][1-9|a-z|-]*)$",
276        )
277        .unwrap();
278        if let Some(caps) = re.captures(&name) {
279            let n = caps.get(1).unwrap().as_str();
280            let s1 = caps.get(3).unwrap().as_str().trim_start_matches("_");
281            let s2 = caps.get(4).unwrap().as_str().trim_start_matches("_");
282
283            match s1 {
284                "append" => match s2 {
285                    "append" => return YoctoVarName::InvalidName,
286                    "remove" => return YoctoVarName::InvalidName,
287                    _ => {
288                        return YoctoVarName::NameAppendOverride((
289                            String::from(n),
290                            String::from(s2),
291                        ))
292                    }
293                },
294                "remove" => match s2 {
295                    "append" => return YoctoVarName::InvalidName,
296                    "remove" => return YoctoVarName::InvalidName,
297                    _ => {
298                        return YoctoVarName::NameRemoveOverride((
299                            String::from(n),
300                            String::from(s2),
301                        ))
302                    }
303                },
304                _ => match s2 {
305                    "append" => {
306                        return YoctoVarName::NameOverrideAppend((
307                            String::from(n),
308                            String::from(s1),
309                        ))
310                    }
311                    "remove" => {
312                        return YoctoVarName::NameOverrideRemove((
313                            String::from(n),
314                            String::from(s1),
315                        ))
316                    }
317                    _ => return YoctoVarName::InvalidName,
318                },
319            }
320        }
321
322        let re =
323            Regex::new(r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)([:|_][a-z][1-9|a-z|-]*)$").unwrap();
324        if let Some(caps) = re.captures(&name) {
325            let n = caps.get(1).unwrap().as_str();
326            let s1 = caps.get(3).unwrap().as_str().trim_start_matches("_");
327            match s1 {
328                "append" => return YoctoVarName::NameValAppend(String::from(n)),
329                "remove" => return YoctoVarName::NameValRemove(String::from(n)),
330                _ => return YoctoVarName::NameOverride((String::from(n), String::from(s1))),
331            }
332        }
333
334        let re = Regex::new(r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)$").unwrap();
335        if let Some(caps) = re.captures(&name) {
336            let n = caps.get(1).unwrap().as_str();
337            return YoctoVarName::Name(String::from(n));
338        }
339
340        YoctoVarName::InvalidName
341    }
342
343    pub fn get_value(&self, vtype: YoctoVarType) -> Option<&str> {
344        match vtype {
345            YoctoVarType::Value => Some(&self.value),
346            YoctoVarType::Override(o) => {
347                if let Some(v) = self.ovalue.get(&o) {
348                    Some(v)
349                } else {
350                    None
351                }
352            }
353            YoctoVarType::Flag(f) => {
354                if let Some(v) = self.fvalue.get(&f) {
355                    Some(v)
356                } else {
357                    None
358                }
359            }
360        }
361    }
362
363    pub fn get_overrides(&self) -> Vec<&str> {
364        let mut v = Vec::new();
365        for k in self.ovalue.keys() {
366            v.push(k.as_str());
367        }
368        v
369    }
370
371    pub fn get_flags(&self) -> Vec<&str> {
372        let mut v = Vec::new();
373        for k in self.fvalue.keys() {
374            v.push(k.as_str());
375        }
376        v
377    }
378
379    pub fn set_value(&mut self, vtype: YoctoVarType, value: &str) {
380        match vtype {
381            YoctoVarType::Value => {
382                self.value.clear();
383                self.value.push_str(&YoctoVar::fix_str(value));
384            }
385            YoctoVarType::Override(o) => {
386                let v = self.ovalue.entry(o).or_insert(String::new());
387                v.clear();
388                v.push_str(YoctoVar::fix_str(value).as_str());
389            }
390            YoctoVarType::Flag(f) => {
391                let v = self.fvalue.entry(f).or_insert(String::new());
392                v.clear();
393                v.push_str(YoctoVar::fix_str(value).as_str());
394            }
395        }
396    }
397
398    pub fn append(&mut self, vtype: YoctoVarType, value: &str) {
399        match vtype {
400            YoctoVarType::Value => {
401                self.value.push_str(&YoctoVar::fix_str(value));
402            }
403            YoctoVarType::Override(o) => {
404                let v = self.ovalue.entry(o).or_insert(String::new());
405                v.push_str(YoctoVar::fix_str(value).as_str());
406            }
407            YoctoVarType::Flag(f) => {
408                let v = self.fvalue.entry(f).or_insert(String::new());
409                v.push_str(YoctoVar::fix_str(value).as_str());
410            }
411        }
412    }
413
414    pub fn prepend(&mut self, vtype: YoctoVarType, value: &str) {
415        let mut nv = YoctoVar::fix_str(value);
416        match vtype {
417            YoctoVarType::Value => {
418                nv.push_str(&self.value);
419                self.value.clear();
420                self.value.push_str(&nv);
421            }
422
423            YoctoVarType::Override(o) => {
424                let v = self.ovalue.entry(o).or_insert(String::new());
425                nv.push_str(&v);
426                v.clear();
427                v.push_str(&nv);
428            }
429
430            YoctoVarType::Flag(f) => {
431                let v = self.fvalue.entry(f).or_insert(String::new());
432                nv.push_str(&v);
433                v.clear();
434                v.push_str(&nv);
435            }
436        }
437    }
438
439    pub fn add_after(&mut self, vtype: YoctoVarType, value: &str) {
440        match vtype {
441            YoctoVarType::Value => {
442                if !self.value.is_empty() {
443                    self.value.push(' ');
444                }
445                self.value.push_str(&YoctoVar::fix_str(value));
446            }
447            YoctoVarType::Override(o) => {
448                let v = self.ovalue.entry(o).or_insert(String::new());
449                if !v.is_empty() {
450                    v.push(' ');
451                }
452                v.push_str(YoctoVar::fix_str(value).as_str());
453            }
454            YoctoVarType::Flag(f) => {
455                let v = self.fvalue.entry(f).or_insert(String::new());
456                if !v.is_empty() {
457                    v.push(' ');
458                }
459                v.push_str(YoctoVar::fix_str(value).as_str());
460            }
461        }
462    }
463
464    pub fn add_before(&mut self, vtype: YoctoVarType, value: &str) {
465        let mut nv = YoctoVar::fix_str(value);
466        match vtype {
467            YoctoVarType::Value => {
468                if !self.value.is_empty() {
469                    nv.push(' ');
470                    nv.push_str(&self.value);
471                }
472                self.value.clear();
473                self.value.push_str(&nv);
474            }
475
476            YoctoVarType::Override(o) => {
477                let v = self.ovalue.entry(o).or_insert(String::new());
478                if !v.is_empty() {
479                    nv.push(' ');
480                    nv.push_str(&v);
481                }
482                v.clear();
483                v.push_str(&nv);
484            }
485
486            YoctoVarType::Flag(f) => {
487                let v = self.fvalue.entry(f).or_insert(String::new());
488                if !v.is_empty() {
489                    nv.push(' ');
490                    nv.push_str(&v);
491                }
492                v.clear();
493                v.push_str(&nv);
494            }
495        }
496    }
497
498    pub fn variables(value_str: &str) -> Vec<String> {
499        let mut result = Vec::new();
500        let mut s = value_str;
501
502        while let Some(a) = s.find("${") {
503            let start = a + 2;
504            if let Some(end) = s[start..].find("}") {
505                let v = &s[start..start + end];
506                if result.iter().find(|x| *x == v).is_none() {
507                    result.push(v.to_string());
508                }
509
510                s = &s[start + end + 1..];
511            } else {
512                break;
513            }
514        }
515
516        result
517    }
518
519    pub fn value(&self, overrides: Option<&str>) -> &str {
520        if let Some(s) = overrides {
521            let mut olist: Vec<&str> = s.split(":").collect();
522            if !olist.is_empty() {
523                olist.reverse();
524                for o in olist {
525                    if let Some(va) = self.ovalue.get(o) {
526                        return va.as_str();
527                    }
528                }
529            }
530        }
531        if self.value.is_empty() {
532            self.default.as_str()
533        } else {
534            self.value.as_str()
535        }
536    }
537
538    pub fn name(&self) -> &str {
539        self.name.as_str()
540    }
541}
542
543impl Display for YoctoVar {
544    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
545        let mut output = String::new();
546        output.push_str(
547            format!(
548                "{} = {}\n",
549                self.name(),
550                self.get_value(YoctoVarType::Value).unwrap_or("")
551            )
552            .as_str(),
553        );
554
555        for o in self.get_overrides() {
556            output.push_str(
557                format!(
558                    "{}_{} = {}\n",
559                    self.name(),
560                    o,
561                    self.get_value(YoctoVarType::Override(o.to_string()))
562                        .unwrap()
563                )
564                .as_str(),
565            );
566        }
567
568        for f in self.get_flags() {
569            output.push_str(
570                format!(
571                    "{}[{}] = {}\n",
572                    self.name(),
573                    f,
574                    self.get_value(YoctoVarType::Flag(f.to_string())).unwrap()
575                )
576                .as_str(),
577            );
578        }
579        write!(f, "{}", output)
580    }
581}
582
583pub struct DataStore {
584    store: HashMap<String, YoctoVar>,
585}
586
587impl DataStore {
588    pub fn new() -> Self {
589        DataStore {
590            store: HashMap::<String, YoctoVar>::new(),
591        }
592    }
593
594    pub fn expand_value(&self, value: &str, gstore: Option<&DataStore>) -> Result<String> {
595        let mut expand_str = YoctoVar::fix_str(value);
596        let variables = YoctoVar::variables(value);
597        let mut overrides = String::new();
598
599        if let Some(d) = gstore {
600            if let Some(o) = d.value("OVERRIDES") {
601                if let Some(ostr) = o.get_value(YoctoVarType::Value) {
602                    overrides.push_str(ostr);
603                }
604            }
605        }
606
607        if let Some(o) = self.store.get("OVERRIDES") {
608            if let Some(ostr) = o.get_value(YoctoVarType::Value) {
609                overrides.push_str(ostr);
610            }
611        }
612
613        for v in variables {
614            if v.starts_with("@") {
615                let mut processed = false;
616                if v.starts_with("@os.path.abspath(") {
617                    if let Some(start) = v.find("(") {
618                        if let Some(end) = v.find(")") {
619                            let u = &v[start + 1..end]
620                                .trim()
621                                .trim_start_matches("\"")
622                                .trim_end_matches("\"")
623                                .trim_start_matches("\'")
624                                .trim_end_matches("\'");
625
626                            if let Ok(p) = fs::canonicalize(u) {
627                                if p.is_dir() {
628                                    let orig = format!("${{{}}}", v);
629                                    expand_str =
630                                        expand_str.replace(orig.as_str(), p.to_str().unwrap());
631                                    processed = true;
632                                }
633                            }
634                        }
635                    }
636                }
637                if !processed {
638                    warn!("Unknown python founction {}", v);
639                    let orig = format!("${{{}}}", v);
640                    expand_str = expand_str.replace(orig.as_str(), "__UNKNOWN__");
641                }
642                continue;
643            }
644
645            let mut var = None;
646
647            if let Some(yv) = self.store.get(v.as_str()) {
648                var = Some(yv);
649            } else {
650                if let Some(d) = gstore {
651                    if let Some(yv) = d.value(v.as_str()) {
652                        var = Some(&yv);
653                    }
654                }
655            }
656
657            let var = var.ok_or(Error::msg(format!("Unknown variable {}.", v)))?;
658
659            let estr = self.expand_value(var.value(Some(&overrides)), gstore)?;
660            let orig = format!("${{{}}}", v);
661            expand_str = expand_str.replace(orig.as_str(), estr.as_str());
662        }
663
664        if expand_str.is_empty() {
665            Ok(value.to_string())
666        } else {
667            Ok(expand_str)
668        }
669    }
670
671    pub fn from_conf_str(&mut self, conf_str: &str, gstore: Option<&DataStore>) -> Result<()> {
672        let conf_str = conf_str
673            .lines()
674            .filter(|l| !l.starts_with("#"))
675            .map(|a| a.trim().to_string())
676            .collect::<Vec<String>>()
677            .join("\n")
678            .replace("\\\n", "");
679
680        let err_statement = Error::msg(format!("Invalid statement"));
681        for l in conf_str.lines() {
682            let v = l.split("??=").collect::<Vec<&str>>();
683            if v.len() == 2 {
684                let val = YoctoVar::fix_str(v[1]);
685                match YoctoVar::parse_name(v[0]) {
686                    YoctoVarName::Name(n) => {
687                        let mut found = false;
688                        let yv = YoctoVar::new_default(&n, &val)?;
689                        if let Some(d) = gstore {
690                            if d.value(&n).is_some() {
691                                found = true;
692                            }
693                        }
694
695                        if !found {
696                            if self.store.get(&n).is_none() {
697                                self.store.insert(n, yv);
698                            }
699                        }
700                    }
701                    _ => return Err(err_statement),
702                }
703                continue;
704            }
705
706            let v = l.split("?=").collect::<Vec<&str>>();
707            if v.len() == 2 {
708                let val = YoctoVar::fix_str(v[1]);
709                let mut found = false;
710                match YoctoVar::parse_name(v[0].trim()) {
711                    YoctoVarName::Name(n) => {
712                        let mut yv = YoctoVar::new(Some(&n))?;
713                        yv.set_value(YoctoVarType::Value, &val);
714
715                        if let Some(d) = gstore {
716                            if d.value(&n).is_some() {
717                                found = true;
718                            }
719                        }
720
721                        if !found {
722                            if self.store.get(&n).is_none() {
723                                self.store.insert(n, yv);
724                            }
725                        }
726                    }
727                    YoctoVarName::NameOverride((n, o)) => {
728                        if let Some(d) = gstore {
729                            if let Some(yv) = d.value(&n) {
730                                if yv.get_value(YoctoVarType::Override(o.clone())).is_some() {
731                                    found = true;
732                                }
733                            }
734                        }
735
736                        if !found {
737                            if let Some(yv) = self.store.get_mut(&n) {
738                                if yv.get_value(YoctoVarType::Override(o.clone())).is_none() {
739                                    yv.set_value(YoctoVarType::Override(o.clone()), &val);
740                                }
741                            } else {
742                                let mut yv = YoctoVar::new(Some(&n))?;
743                                yv.set_value(YoctoVarType::Override(o.clone()), &val);
744                                self.store.insert(n, yv);
745                            }
746                        }
747                    }
748                    YoctoVarName::NameFlag((n, f)) => {
749                        if let Some(d) = gstore {
750                            if let Some(yv) = d.value(&n) {
751                                if yv.get_value(YoctoVarType::Flag(f.clone())).is_some() {
752                                    found = true;
753                                }
754                            }
755                        }
756
757                        if !found {
758                            if let Some(yv) = self.store.get_mut(&n) {
759                                if yv.get_value(YoctoVarType::Flag(f.clone())).is_none() {
760                                    yv.set_value(YoctoVarType::Flag(f.clone()), &val);
761                                }
762                            } else {
763                                let mut yv = YoctoVar::new(Some(&n))?;
764                                yv.set_value(YoctoVarType::Flag(f.clone()), &val);
765                                self.store.insert(n, yv);
766                            }
767                        }
768                    }
769                    _ => return Err(err_statement),
770                }
771
772                continue;
773            }
774
775            let v = l.split(":=").collect::<Vec<&str>>();
776            if v.len() == 2 {
777                let val = YoctoVar::fix_str(v[1]);
778                match YoctoVar::parse_name(v[0].trim()) {
779                    YoctoVarName::Name(n) => {
780                        let ev = self.expand_value(&val, gstore)?;
781                        if let Some(yv) = self.store.get_mut(&n) {
782                            yv.set_value(YoctoVarType::Value, ev.as_str());
783                        } else {
784                            let mut yv = YoctoVar::new(Some(&n))?;
785                            yv.set_value(YoctoVarType::Value, ev.as_str());
786                            self.store.insert(n, yv);
787                        }
788                    }
789
790                    YoctoVarName::NameOverride((n, o)) => {
791                        let ev = self.expand_value(&val, gstore)?;
792                        if let Some(yv) = self.store.get_mut(&n) {
793                            yv.set_value(YoctoVarType::Override(o.clone()), ev.as_str());
794                        } else {
795                            let ev = self.expand_value(&val, gstore)?;
796                            let mut yv = YoctoVar::new(Some(&n))?;
797                            yv.set_value(YoctoVarType::Override(o.clone()), ev.as_str());
798                            self.store.insert(n, yv);
799                        }
800                    }
801
802                    YoctoVarName::NameFlag((n, f)) => {
803                        let ev = self.expand_value(&val, gstore)?;
804                        if let Some(yv) = self.store.get_mut(&n) {
805                            yv.set_value(YoctoVarType::Flag(f.clone()), ev.as_str());
806                        } else {
807                            let ev = self.expand_value(&val, gstore)?;
808                            let mut yv = YoctoVar::new(Some(&n))?;
809                            yv.set_value(YoctoVarType::Flag(f.clone()), ev.as_str());
810                            self.store.insert(n, yv);
811                        }
812                    }
813
814                    _ => return Err(err_statement),
815                }
816                continue;
817            }
818
819            let v = l.split("+=").collect::<Vec<&str>>();
820            if v.len() == 2 {
821                let val = YoctoVar::fix_str(v[1]);
822                match YoctoVar::parse_name(v[0].trim()) {
823                    YoctoVarName::Name(n) => {
824                        if let Some(yv) = self.store.get_mut(&n) {
825                            yv.add_after(YoctoVarType::Value, &val);
826                        } else {
827                            let mut yv = YoctoVar::new(Some(&n))?;
828                            yv.add_after(YoctoVarType::Value, &val);
829                            self.store.insert(n, yv);
830                        }
831                    }
832                    YoctoVarName::NameOverride((n, o)) => {
833                        if let Some(yv) = self.store.get_mut(&n) {
834                            yv.add_after(YoctoVarType::Override(o.clone()), &val);
835                        } else {
836                            let mut yv = YoctoVar::new(Some(&n))?;
837                            yv.add_after(YoctoVarType::Override(o.clone()), &val);
838                            self.store.insert(n, yv);
839                        }
840                    }
841                    YoctoVarName::NameFlag((n, f)) => {
842                        if let Some(yv) = self.store.get_mut(&n) {
843                            yv.add_after(YoctoVarType::Flag(f.clone()), &val);
844                        } else {
845                            let mut yv = YoctoVar::new(Some(&n))?;
846                            yv.add_after(YoctoVarType::Flag(f.clone()), &val);
847                            self.store.insert(n, yv);
848                        }
849                    }
850                    _ => return Err(err_statement),
851                }
852
853                continue;
854            }
855
856            let v = l.split("=+").collect::<Vec<&str>>();
857            if v.len() == 2 {
858                let val = YoctoVar::fix_str(v[1]);
859                match YoctoVar::parse_name(v[0].trim()) {
860                    YoctoVarName::Name(n) => {
861                        if let Some(yv) = self.store.get_mut(&n) {
862                            yv.add_before(YoctoVarType::Value, &val);
863                        } else {
864                            let mut yv = YoctoVar::new(Some(&n))?;
865                            yv.add_before(YoctoVarType::Value, &val);
866                            self.store.insert(n, yv);
867                        }
868                    }
869                    YoctoVarName::NameOverride((n, o)) => {
870                        if let Some(yv) = self.store.get_mut(&n) {
871                            yv.add_before(YoctoVarType::Override(o.clone()), &val);
872                        } else {
873                            let mut yv = YoctoVar::new(Some(&n))?;
874                            yv.add_before(YoctoVarType::Override(o.clone()), &val);
875                            self.store.insert(n, yv);
876                        }
877                    }
878                    YoctoVarName::NameFlag((n, f)) => {
879                        if let Some(yv) = self.store.get_mut(&n) {
880                            yv.add_before(YoctoVarType::Flag(f.clone()), &val);
881                        } else {
882                            let mut yv = YoctoVar::new(Some(&n))?;
883                            yv.add_before(YoctoVarType::Flag(f.clone()), &val);
884                            self.store.insert(n, yv);
885                        }
886                    }
887                    _ => return Err(err_statement),
888                }
889                continue;
890            }
891
892            let v = l.split(".=").collect::<Vec<&str>>();
893            if v.len() == 2 {
894                let val = YoctoVar::fix_str(v[1]);
895                match YoctoVar::parse_name(v[0]) {
896                    YoctoVarName::Name(n) => {
897                        if let Some(yv) = self.store.get_mut(&n) {
898                            yv.append(YoctoVarType::Value, &val);
899                        } else {
900                            let mut yv = YoctoVar::new(Some(&n))?;
901                            yv.append(YoctoVarType::Value, &val);
902                            self.store.insert(n, yv);
903                        }
904                    }
905                    YoctoVarName::NameOverride((n, o)) => {
906                        if let Some(yv) = self.store.get_mut(&n) {
907                            yv.append(YoctoVarType::Override(o.clone()), &val);
908                        } else {
909                            let mut yv = YoctoVar::new(Some(&n))?;
910                            yv.append(YoctoVarType::Override(o.clone()), &val);
911                            self.store.insert(n, yv);
912                        }
913                    }
914                    YoctoVarName::NameFlag((n, f)) => {
915                        if let Some(yv) = self.store.get_mut(&n) {
916                            yv.append(YoctoVarType::Flag(f.clone()), &val);
917                        } else {
918                            let mut yv = YoctoVar::new(Some(&n))?;
919                            yv.append(YoctoVarType::Flag(f.clone()), &val);
920                            self.store.insert(n, yv);
921                        }
922                    }
923                    _ => return Err(err_statement),
924                }
925                continue;
926            }
927
928            let v = l.split("=.").collect::<Vec<&str>>();
929            if v.len() == 2 {
930                let val = YoctoVar::fix_str(v[1]);
931                match YoctoVar::parse_name(v[0]) {
932                    YoctoVarName::Name(n) => {
933                        if let Some(yv) = self.store.get_mut(&n) {
934                            yv.prepend(YoctoVarType::Value, &val);
935                        } else {
936                            let mut yv = YoctoVar::new(Some(&n))?;
937                            yv.prepend(YoctoVarType::Value, &val);
938                            self.store.insert(n, yv);
939                        }
940                    }
941                    YoctoVarName::NameOverride((n, o)) => {
942                        if let Some(yv) = self.store.get_mut(&n) {
943                            yv.prepend(YoctoVarType::Override(o.clone()), &val);
944                        } else {
945                            let mut yv = YoctoVar::new(Some(&n))?;
946                            yv.prepend(YoctoVarType::Override(o.clone()), &val);
947                            self.store.insert(n, yv);
948                        }
949                    }
950                    YoctoVarName::NameFlag((n, f)) => {
951                        if let Some(yv) = self.store.get_mut(&n) {
952                            yv.prepend(YoctoVarType::Flag(f.clone()), &val);
953                        } else {
954                            let mut yv = YoctoVar::new(Some(&n))?;
955                            yv.prepend(YoctoVarType::Flag(f.clone()), &val);
956                            self.store.insert(n, yv);
957                        }
958                    }
959                    _ => return Err(err_statement),
960                }
961                continue;
962            }
963
964            /* this must be the last one */
965            let v = l.split("=").collect::<Vec<&str>>();
966            if v.len() == 2 {
967                let key_name = YoctoVar::key_name(v[0])?;
968                if let Some(yv) = self.store.get_mut(&key_name) {
969                    yv.update(v[0], YoctoVar::fix_str(v[1]).as_str())?;
970                } else {
971                    let mut yv = YoctoVar::new(Some(&key_name))?;
972                    yv.update(v[0], YoctoVar::fix_str(v[1]).as_str())?;
973                    self.store.insert(key_name, yv);
974                }
975            }
976        }
977
978        Ok(())
979    }
980
981    pub fn from_conf_file(&mut self, file: &str, gstore: Option<&DataStore>) -> Result<()> {
982        self.from_conf_str(
983            fs::read_to_string(file)
984                .with_context(|| format!("Failed to read {}", file))?
985                .as_str(),
986            gstore,
987        )
988    }
989
990    pub fn value(&self, key: &str) -> Option<&YoctoVar> {
991        self.store.get(key)
992    }
993
994    pub fn data_store(&self) -> &HashMap<String, YoctoVar> {
995        &self.store
996    }
997
998    pub fn add(&mut self, yv: YoctoVar) {
999        let key = yv.name();
1000        self.store.insert(key.to_string(), yv);
1001    }
1002}
1003
1004impl Display for DataStore {
1005    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1006        let mut output = String::new();
1007        for (_k, yv) in self.store.iter() {
1008            output.push_str(&format!("  {}", yv));
1009        }
1010
1011        write!(f, "{}", output)
1012    }
1013}
1014
1015#[cfg(test)]
1016mod yocto_test;