use serde::Deserialize;
pub fn parse_yaml(yaml_str: &str) -> anyhow::Result<Vec<SpliceRule>> {
let config: ConfigFile = serde_yaml::from_str(yaml_str)?;
assert_eq!(config.version, 1);
Ok(config.to_splice_rules())
}
#[derive(Debug, Deserialize)]
pub struct ConfigFile {
pub version: u32,
pub rules: Vec<YamlRule>,
}
#[derive(Debug, Deserialize)]
pub struct YamlRule {
before: Option<YamlStrategyBefore>,
between: Option<YamlStrategyBetween>,
inject: Vec<Injection>,
}
#[derive(Debug, Deserialize)]
pub struct YamlStrategyBefore {
interface: String,
provider: Option<YamlProviderOpt>,
}
#[derive(Debug, Deserialize)]
pub struct YamlStrategyBetween {
inner: YamlProviderReq,
outer: YamlProviderReq,
interface: String,
}
#[derive(Debug, Deserialize)]
pub struct YamlProviderReq {
name: String,
alias: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct YamlProviderOpt {
name: Option<String>,
alias: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Injection {
pub name: String,
pub path: Option<String>,
}
#[derive(Debug)]
pub enum SpliceRule {
Before {
interface: String,
provider_name: Option<String>,
provider_alias: Option<String>,
inject: Vec<Injection>,
},
Between {
interface: String,
inner_name: String,
inner_alias: Option<String>,
outer_name: String,
outer_alias: Option<String>,
inject: Vec<Injection>,
},
}
impl ConfigFile {
pub fn to_splice_rules(&self) -> Vec<SpliceRule> {
self.rules
.iter()
.map(
|YamlRule {
before,
between,
inject,
}| {
if before.is_some() && between.is_some() {
panic!("insert error here (should have one or the other, not BOTH!)");
}
if let Some(YamlStrategyBefore {
interface,
provider,
}) = before
{
SpliceRule::Before {
interface: interface.clone(),
provider_name: if let Some(prov) = provider {
prov.name.clone()
} else {
None
},
provider_alias: if let Some(prov) = provider {
prov.alias.clone()
} else {
None
},
inject: (*inject).clone(),
}
} else if let Some(YamlStrategyBetween {
interface,
inner,
outer,
}) = between
{
SpliceRule::Between {
interface: interface.clone(),
inner_name: inner.name.clone(),
inner_alias: inner.alias.clone(),
outer_name: outer.name.clone(),
outer_alias: outer.alias.clone(),
inject: (*inject).clone(),
}
} else {
panic!("insert error here (should have one or the other, not neither!)");
}
},
)
.collect()
}
}