#[allow(unused)]
use {
anyhow::{Context, Error, Result},
jlogger::{jdebug, jerror, jinfo, JloggerBuilder},
log::{debug, info, warn},
regex::Regex,
std::{
collections::HashMap,
fmt::Display,
fs,
path::{Path, PathBuf},
},
};
pub enum YoctoVarName {
Name(String),
NameValAppend(String),
NameValRemove(String),
NameFlag((String, String)),
NameOverride((String, String)),
NameOverrideAppend((String, String)),
NameOverrideRemove((String, String)),
NameAppendOverride((String, String)),
NameRemoveOverride((String, String)),
InvalidName,
}
pub enum YoctoVarType {
Value,
Override(String),
Flag(String),
}
pub struct YoctoVar {
name: String,
value: String,
ovalue: HashMap<String, String>,
fvalue: HashMap<String, String>,
default: String,
}
impl YoctoVar {
pub fn valid_varable_name(name: &str) -> bool {
Regex::new(r"^[A-Z][(A-Z)|(0-9)|_]*$")
.unwrap()
.is_match(name)
}
pub fn valid_override(s: &str) -> bool {
Regex::new(r"^[a-z]([a-z|0-9|-])*$").unwrap().is_match(s)
}
pub fn fix_str(s: &str) -> String {
s.trim()
.trim_start_matches("\"")
.trim_end_matches("\"")
.trim()
.to_string()
}
pub fn new(statement: Option<&str>) -> Result<Self> {
let name = statement
.map(|a| YoctoVar::fix_str(a))
.unwrap_or_else(|| String::from("UNDEFINE"));
if !YoctoVar::valid_varable_name(&name) {
return Err(Error::msg(format!("Invalid name {}", name)));
}
let n = YoctoVar {
name,
value: String::new(),
default: String::new(),
ovalue: HashMap::<String, String>::new(),
fvalue: HashMap::<String, String>::new(),
};
Ok(n)
}
pub fn new_default(name: &str, val: &str) -> Result<Self> {
let name = YoctoVar::fix_str(name);
let err_name = Error::msg(format!("Invalid name {}", name));
if !YoctoVar::valid_varable_name(&name) {
return Err(err_name);
}
Ok(YoctoVar {
name,
value: String::new(),
default: YoctoVar::fix_str(val),
ovalue: HashMap::<String, String>::new(),
fvalue: HashMap::<String, String>::new(),
})
}
pub fn set_default_value(&mut self, val: &str) {
self.default = YoctoVar::fix_str(val);
}
pub fn get_default_value(&self) -> &str {
self.default.as_str()
}
pub fn update(&mut self, statement: &str, value: &str) -> Result<()> {
let statement = YoctoVar::fix_str(statement);
let err_statement = Error::msg(format!("Invalid statement {}", statement));
let err_name = Error::msg(format!("Invalid name {} != {}", statement, self.name));
let val = value;
let var_remove = |v: &mut String, val: &str| {
if v.as_str() == val {
v.clear();
} else {
let val_fix_0 = format!(" {} ", val);
let val_fix_1 = format!("{} ", val);
let val_fix_2 = format!(" {}", val);
let mut nv = v.replace(&val_fix_0, "");
nv = nv.replace(&val_fix_1, "");
nv = nv.replace(&val_fix_2, "");
v.clear();
v.push_str(&nv);
}
};
match YoctoVar::parse_name(&statement) {
YoctoVarName::Name(n) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
self.value.clear();
self.value.push_str(val);
}
YoctoVarName::NameValAppend(n) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
self.value.push_str(val);
}
YoctoVarName::NameValRemove(n) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
var_remove(&mut self.value, val);
}
YoctoVarName::NameFlag((n, f)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let v = self.fvalue.entry(f).or_insert(String::new());
v.clear();
v.push_str(val);
}
YoctoVarName::NameOverride((n, o)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let v = self.ovalue.entry(o).or_insert(String::new());
v.clear();
v.push_str(val);
}
YoctoVarName::NameOverrideAppend((n, o)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let v = self.ovalue.entry(o).or_insert(String::new());
v.push_str(val);
}
YoctoVarName::NameOverrideRemove((n, o)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let v = self.ovalue.entry(o).or_insert(String::new());
var_remove(v, val);
}
YoctoVarName::NameAppendOverride((n, o)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let mut nvalue = self.value.clone();
nvalue.push_str(val);
let v = self.ovalue.entry(o).or_insert(String::new());
v.clear();
v.push_str(&nvalue);
}
YoctoVarName::NameRemoveOverride((n, o)) => {
if self.name == "UNDEFINE" {
self.name.clear();
self.name.push_str(&n);
} else if n != self.name {
return Err(err_name);
}
let mut nvalue = self.value.clone();
var_remove(&mut nvalue, val);
let v = self.ovalue.entry(o).or_insert(String::new());
v.clear();
v.push_str(&nvalue);
}
_ => return Err(err_statement),
}
Ok(())
}
pub fn key_name<'a>(name: &'a str) -> Result<String> {
match YoctoVar::parse_name(name) {
YoctoVarName::Name(n) => Ok(n.to_string()),
YoctoVarName::NameValAppend(n) => Ok(n.to_string()),
YoctoVarName::NameValRemove(n) => Ok(n.to_string()),
YoctoVarName::NameFlag((n, _)) => Ok(n.to_string()),
YoctoVarName::NameOverride((n, _)) => Ok(n.to_string()),
YoctoVarName::NameOverrideAppend((n, _)) => Ok(n.to_string()),
YoctoVarName::NameOverrideRemove((n, _)) => Ok(n.to_string()),
YoctoVarName::NameAppendOverride((n, _)) => Ok(n.to_string()),
YoctoVarName::NameRemoveOverride((n, _)) => Ok(n.to_string()),
YoctoVarName::InvalidName => Err(Error::msg(format!("Invalid name {}", name))),
}
}
pub fn parse_name<'a>(name: &'a str) -> YoctoVarName {
let name = YoctoVar::fix_str(name);
let re =
Regex::new(r"([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)\[([a-z]([a-z|0-9|_]*[a-z|0-9])*)\]")
.unwrap();
if let Some(caps) = re.captures(&name) {
let n = caps.get(1).unwrap().as_str();
let f = caps.get(3).unwrap().as_str();
return YoctoVarName::NameFlag((String::from(n), String::from(f)));
}
let re = Regex::new(
r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)([:|_][a-z][1-9|a-z|-]*)([:|_][a-z][1-9|a-z|-]*)$",
)
.unwrap();
if let Some(caps) = re.captures(&name) {
let n = caps.get(1).unwrap().as_str();
let s1 = caps.get(3).unwrap().as_str().trim_start_matches("_");
let s2 = caps.get(4).unwrap().as_str().trim_start_matches("_");
match s1 {
"append" => match s2 {
"append" => return YoctoVarName::InvalidName,
"remove" => return YoctoVarName::InvalidName,
_ => {
return YoctoVarName::NameAppendOverride((
String::from(n),
String::from(s2),
))
}
},
"remove" => match s2 {
"append" => return YoctoVarName::InvalidName,
"remove" => return YoctoVarName::InvalidName,
_ => {
return YoctoVarName::NameRemoveOverride((
String::from(n),
String::from(s2),
))
}
},
_ => match s2 {
"append" => {
return YoctoVarName::NameOverrideAppend((
String::from(n),
String::from(s1),
))
}
"remove" => {
return YoctoVarName::NameOverrideRemove((
String::from(n),
String::from(s1),
))
}
_ => return YoctoVarName::InvalidName,
},
}
}
let re =
Regex::new(r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)([:|_][a-z][1-9|a-z|-]*)$").unwrap();
if let Some(caps) = re.captures(&name) {
let n = caps.get(1).unwrap().as_str();
let s1 = caps.get(3).unwrap().as_str().trim_start_matches("_");
match s1 {
"append" => return YoctoVarName::NameValAppend(String::from(n)),
"remove" => return YoctoVarName::NameValRemove(String::from(n)),
_ => return YoctoVarName::NameOverride((String::from(n), String::from(s1))),
}
}
let re = Regex::new(r"^([A-Z|_]([A-Z|_|0-9]*[A-Z|0-9])*)$").unwrap();
if let Some(caps) = re.captures(&name) {
let n = caps.get(1).unwrap().as_str();
return YoctoVarName::Name(String::from(n));
}
YoctoVarName::InvalidName
}
pub fn get_value(&self, vtype: YoctoVarType) -> Option<&str> {
match vtype {
YoctoVarType::Value => Some(&self.value),
YoctoVarType::Override(o) => {
if let Some(v) = self.ovalue.get(&o) {
Some(v)
} else {
None
}
}
YoctoVarType::Flag(f) => {
if let Some(v) = self.fvalue.get(&f) {
Some(v)
} else {
None
}
}
}
}
pub fn get_overrides(&self) -> Vec<&str> {
let mut v = Vec::new();
for k in self.ovalue.keys() {
v.push(k.as_str());
}
v
}
pub fn get_flags(&self) -> Vec<&str> {
let mut v = Vec::new();
for k in self.fvalue.keys() {
v.push(k.as_str());
}
v
}
pub fn set_value(&mut self, vtype: YoctoVarType, value: &str) {
match vtype {
YoctoVarType::Value => {
self.value.clear();
self.value.push_str(&YoctoVar::fix_str(value));
}
YoctoVarType::Override(o) => {
let v = self.ovalue.entry(o).or_insert(String::new());
v.clear();
v.push_str(YoctoVar::fix_str(value).as_str());
}
YoctoVarType::Flag(f) => {
let v = self.fvalue.entry(f).or_insert(String::new());
v.clear();
v.push_str(YoctoVar::fix_str(value).as_str());
}
}
}
pub fn append(&mut self, vtype: YoctoVarType, value: &str) {
match vtype {
YoctoVarType::Value => {
self.value.push_str(&YoctoVar::fix_str(value));
}
YoctoVarType::Override(o) => {
let v = self.ovalue.entry(o).or_insert(String::new());
v.push_str(YoctoVar::fix_str(value).as_str());
}
YoctoVarType::Flag(f) => {
let v = self.fvalue.entry(f).or_insert(String::new());
v.push_str(YoctoVar::fix_str(value).as_str());
}
}
}
pub fn prepend(&mut self, vtype: YoctoVarType, value: &str) {
let mut nv = YoctoVar::fix_str(value);
match vtype {
YoctoVarType::Value => {
nv.push_str(&self.value);
self.value.clear();
self.value.push_str(&nv);
}
YoctoVarType::Override(o) => {
let v = self.ovalue.entry(o).or_insert(String::new());
nv.push_str(&v);
v.clear();
v.push_str(&nv);
}
YoctoVarType::Flag(f) => {
let v = self.fvalue.entry(f).or_insert(String::new());
nv.push_str(&v);
v.clear();
v.push_str(&nv);
}
}
}
pub fn add_after(&mut self, vtype: YoctoVarType, value: &str) {
match vtype {
YoctoVarType::Value => {
if !self.value.is_empty() {
self.value.push(' ');
}
self.value.push_str(&YoctoVar::fix_str(value));
}
YoctoVarType::Override(o) => {
let v = self.ovalue.entry(o).or_insert(String::new());
if !v.is_empty() {
v.push(' ');
}
v.push_str(YoctoVar::fix_str(value).as_str());
}
YoctoVarType::Flag(f) => {
let v = self.fvalue.entry(f).or_insert(String::new());
if !v.is_empty() {
v.push(' ');
}
v.push_str(YoctoVar::fix_str(value).as_str());
}
}
}
pub fn add_before(&mut self, vtype: YoctoVarType, value: &str) {
let mut nv = YoctoVar::fix_str(value);
match vtype {
YoctoVarType::Value => {
if !self.value.is_empty() {
nv.push(' ');
nv.push_str(&self.value);
}
self.value.clear();
self.value.push_str(&nv);
}
YoctoVarType::Override(o) => {
let v = self.ovalue.entry(o).or_insert(String::new());
if !v.is_empty() {
nv.push(' ');
nv.push_str(&v);
}
v.clear();
v.push_str(&nv);
}
YoctoVarType::Flag(f) => {
let v = self.fvalue.entry(f).or_insert(String::new());
if !v.is_empty() {
nv.push(' ');
nv.push_str(&v);
}
v.clear();
v.push_str(&nv);
}
}
}
pub fn variables(value_str: &str) -> Vec<String> {
let mut result = Vec::new();
let mut s = value_str;
while let Some(a) = s.find("${") {
let start = a + 2;
if let Some(end) = s[start..].find("}") {
let v = &s[start..start + end];
if result.iter().find(|x| *x == v).is_none() {
result.push(v.to_string());
}
s = &s[start + end + 1..];
} else {
break;
}
}
result
}
pub fn value(&self, overrides: Option<&str>) -> &str {
if let Some(s) = overrides {
let mut olist: Vec<&str> = s.split(":").collect();
if !olist.is_empty() {
olist.reverse();
for o in olist {
if let Some(va) = self.ovalue.get(o) {
return va.as_str();
}
}
}
}
if self.value.is_empty() {
self.default.as_str()
} else {
self.value.as_str()
}
}
pub fn name(&self) -> &str {
self.name.as_str()
}
}
impl Display for YoctoVar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut output = String::new();
output.push_str(
format!(
"{} = {}\n",
self.name(),
self.get_value(YoctoVarType::Value).unwrap_or("")
)
.as_str(),
);
for o in self.get_overrides() {
output.push_str(
format!(
"{}_{} = {}\n",
self.name(),
o,
self.get_value(YoctoVarType::Override(o.to_string()))
.unwrap()
)
.as_str(),
);
}
for f in self.get_flags() {
output.push_str(
format!(
"{}[{}] = {}\n",
self.name(),
f,
self.get_value(YoctoVarType::Flag(f.to_string())).unwrap()
)
.as_str(),
);
}
write!(f, "{}", output)
}
}
pub struct DataStore {
store: HashMap<String, YoctoVar>,
}
impl DataStore {
pub fn new() -> Self {
DataStore {
store: HashMap::<String, YoctoVar>::new(),
}
}
pub fn expand_value(&self, value: &str, gstore: Option<&DataStore>) -> Result<String> {
let mut expand_str = YoctoVar::fix_str(value);
let variables = YoctoVar::variables(value);
let mut overrides = String::new();
if let Some(d) = gstore {
if let Some(o) = d.value("OVERRIDES") {
if let Some(ostr) = o.get_value(YoctoVarType::Value) {
overrides.push_str(ostr);
}
}
}
if let Some(o) = self.store.get("OVERRIDES") {
if let Some(ostr) = o.get_value(YoctoVarType::Value) {
overrides.push_str(ostr);
}
}
for v in variables {
if v.starts_with("@") {
let mut processed = false;
if v.starts_with("@os.path.abspath(") {
if let Some(start) = v.find("(") {
if let Some(end) = v.find(")") {
let u = &v[start + 1..end]
.trim()
.trim_start_matches("\"")
.trim_end_matches("\"")
.trim_start_matches("\'")
.trim_end_matches("\'");
if let Ok(p) = fs::canonicalize(u) {
if p.is_dir() {
let orig = format!("${{{}}}", v);
expand_str =
expand_str.replace(orig.as_str(), p.to_str().unwrap());
processed = true;
}
}
}
}
}
if !processed {
warn!("Unknown python founction {}", v);
let orig = format!("${{{}}}", v);
expand_str = expand_str.replace(orig.as_str(), "__UNKNOWN__");
}
continue;
}
let mut var = None;
if let Some(yv) = self.store.get(v.as_str()) {
var = Some(yv);
} else {
if let Some(d) = gstore {
if let Some(yv) = d.value(v.as_str()) {
var = Some(&yv);
}
}
}
let var = var.ok_or(Error::msg(format!("Unknown variable {}.", v)))?;
let estr = self.expand_value(var.value(Some(&overrides)), gstore)?;
let orig = format!("${{{}}}", v);
expand_str = expand_str.replace(orig.as_str(), estr.as_str());
}
if expand_str.is_empty() {
Ok(value.to_string())
} else {
Ok(expand_str)
}
}
pub fn from_conf_str(&mut self, conf_str: &str, gstore: Option<&DataStore>) -> Result<()> {
let conf_str = conf_str
.lines()
.filter(|l| !l.starts_with("#"))
.map(|a| a.trim().to_string())
.collect::<Vec<String>>()
.join("\n")
.replace("\\\n", "");
let err_statement = Error::msg(format!("Invalid statement"));
for l in conf_str.lines() {
let v = l.split("??=").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0]) {
YoctoVarName::Name(n) => {
let mut found = false;
let yv = YoctoVar::new_default(&n, &val)?;
if let Some(d) = gstore {
if d.value(&n).is_some() {
found = true;
}
}
if !found {
if self.store.get(&n).is_none() {
self.store.insert(n, yv);
}
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split("?=").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
let mut found = false;
match YoctoVar::parse_name(v[0].trim()) {
YoctoVarName::Name(n) => {
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Value, &val);
if let Some(d) = gstore {
if d.value(&n).is_some() {
found = true;
}
}
if !found {
if self.store.get(&n).is_none() {
self.store.insert(n, yv);
}
}
}
YoctoVarName::NameOverride((n, o)) => {
if let Some(d) = gstore {
if let Some(yv) = d.value(&n) {
if yv.get_value(YoctoVarType::Override(o.clone())).is_some() {
found = true;
}
}
}
if !found {
if let Some(yv) = self.store.get_mut(&n) {
if yv.get_value(YoctoVarType::Override(o.clone())).is_none() {
yv.set_value(YoctoVarType::Override(o.clone()), &val);
}
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Override(o.clone()), &val);
self.store.insert(n, yv);
}
}
}
YoctoVarName::NameFlag((n, f)) => {
if let Some(d) = gstore {
if let Some(yv) = d.value(&n) {
if yv.get_value(YoctoVarType::Flag(f.clone())).is_some() {
found = true;
}
}
}
if !found {
if let Some(yv) = self.store.get_mut(&n) {
if yv.get_value(YoctoVarType::Flag(f.clone())).is_none() {
yv.set_value(YoctoVarType::Flag(f.clone()), &val);
}
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Flag(f.clone()), &val);
self.store.insert(n, yv);
}
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split(":=").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0].trim()) {
YoctoVarName::Name(n) => {
let ev = self.expand_value(&val, gstore)?;
if let Some(yv) = self.store.get_mut(&n) {
yv.set_value(YoctoVarType::Value, ev.as_str());
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Value, ev.as_str());
self.store.insert(n, yv);
}
}
YoctoVarName::NameOverride((n, o)) => {
let ev = self.expand_value(&val, gstore)?;
if let Some(yv) = self.store.get_mut(&n) {
yv.set_value(YoctoVarType::Override(o.clone()), ev.as_str());
} else {
let ev = self.expand_value(&val, gstore)?;
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Override(o.clone()), ev.as_str());
self.store.insert(n, yv);
}
}
YoctoVarName::NameFlag((n, f)) => {
let ev = self.expand_value(&val, gstore)?;
if let Some(yv) = self.store.get_mut(&n) {
yv.set_value(YoctoVarType::Flag(f.clone()), ev.as_str());
} else {
let ev = self.expand_value(&val, gstore)?;
let mut yv = YoctoVar::new(Some(&n))?;
yv.set_value(YoctoVarType::Flag(f.clone()), ev.as_str());
self.store.insert(n, yv);
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split("+=").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0].trim()) {
YoctoVarName::Name(n) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_after(YoctoVarType::Value, &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_after(YoctoVarType::Value, &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameOverride((n, o)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_after(YoctoVarType::Override(o.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_after(YoctoVarType::Override(o.clone()), &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameFlag((n, f)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_after(YoctoVarType::Flag(f.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_after(YoctoVarType::Flag(f.clone()), &val);
self.store.insert(n, yv);
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split("=+").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0].trim()) {
YoctoVarName::Name(n) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_before(YoctoVarType::Value, &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_before(YoctoVarType::Value, &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameOverride((n, o)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_before(YoctoVarType::Override(o.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_before(YoctoVarType::Override(o.clone()), &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameFlag((n, f)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.add_before(YoctoVarType::Flag(f.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.add_before(YoctoVarType::Flag(f.clone()), &val);
self.store.insert(n, yv);
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split(".=").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0]) {
YoctoVarName::Name(n) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.append(YoctoVarType::Value, &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.append(YoctoVarType::Value, &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameOverride((n, o)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.append(YoctoVarType::Override(o.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.append(YoctoVarType::Override(o.clone()), &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameFlag((n, f)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.append(YoctoVarType::Flag(f.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.append(YoctoVarType::Flag(f.clone()), &val);
self.store.insert(n, yv);
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split("=.").collect::<Vec<&str>>();
if v.len() == 2 {
let val = YoctoVar::fix_str(v[1]);
match YoctoVar::parse_name(v[0]) {
YoctoVarName::Name(n) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.prepend(YoctoVarType::Value, &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.prepend(YoctoVarType::Value, &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameOverride((n, o)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.prepend(YoctoVarType::Override(o.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.prepend(YoctoVarType::Override(o.clone()), &val);
self.store.insert(n, yv);
}
}
YoctoVarName::NameFlag((n, f)) => {
if let Some(yv) = self.store.get_mut(&n) {
yv.prepend(YoctoVarType::Flag(f.clone()), &val);
} else {
let mut yv = YoctoVar::new(Some(&n))?;
yv.prepend(YoctoVarType::Flag(f.clone()), &val);
self.store.insert(n, yv);
}
}
_ => return Err(err_statement),
}
continue;
}
let v = l.split("=").collect::<Vec<&str>>();
if v.len() == 2 {
let key_name = YoctoVar::key_name(v[0])?;
if let Some(yv) = self.store.get_mut(&key_name) {
yv.update(v[0], YoctoVar::fix_str(v[1]).as_str())?;
} else {
let mut yv = YoctoVar::new(Some(&key_name))?;
yv.update(v[0], YoctoVar::fix_str(v[1]).as_str())?;
self.store.insert(key_name, yv);
}
}
}
Ok(())
}
pub fn from_conf_file(&mut self, file: &str, gstore: Option<&DataStore>) -> Result<()> {
self.from_conf_str(
fs::read_to_string(file)
.with_context(|| format!("Failed to read {}", file))?
.as_str(),
gstore,
)
}
pub fn value(&self, key: &str) -> Option<&YoctoVar> {
self.store.get(key)
}
pub fn data_store(&self) -> &HashMap<String, YoctoVar> {
&self.store
}
pub fn add(&mut self, yv: YoctoVar) {
let key = yv.name();
self.store.insert(key.to_string(), yv);
}
}
impl Display for DataStore {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut output = String::new();
for (_k, yv) in self.store.iter() {
output.push_str(&format!(" {}", yv));
}
write!(f, "{}", output)
}
}
#[cfg(test)]
mod yocto_test;