use std::collections::HashMap;
use itertools::Itertools;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] pub(crate) struct Workflow {
pub version: String,
pub capture: Option<String>,
pub env: Option<HashMap<String, String>>,
pub nodes: HashMap<String, Node>,
}
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub(crate) struct Shell {
pub program: String,
pub args: Vec<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub(crate) struct Node {
pub description: Option<String>,
pub pre: Option<Vec<String>>,
pub matrix: Option<Matrix>,
pub tasks: Vec<Task>,
pub capture: Option<String>,
pub env: Option<HashMap<String, String>>,
pub shell: Option<Shell>,
pub workdir: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub(crate) enum Matrix {
Dense {
drop: Option<String>,
dimensions: Vec<Vec<MatrixCell>>,
},
Sparse {
dimensions: Vec<Vec<MatrixCell>>,
keep: Option<String>,
},
}
impl Matrix {
pub(crate) fn compile(&self) -> Result<Vec<crate::plan::Invocation>, crate::error::Error> {
let (dimensions, regex) = match self {
| Self::Dense { drop, dimensions } => (dimensions, drop),
| Self::Sparse { keep, dimensions } => (dimensions, keep),
};
let regex = match regex {
| Some(v) => Some(fancy_regex::Regex::new(&v)?),
| None => None,
};
let dims_widx = dimensions.iter().map(|d_x| {
let mut y = 0usize;
d_x.iter()
.map(|d_y| {
y += 1;
(y - 1, d_y)
})
.collect_vec()
});
let cp = dims_widx.multi_cartesian_product();
let mut v = Vec::<crate::plan::Invocation>::new();
for next in cp {
let coords = next.iter().map(|v| format!("{}", v.0)).join(",");
match self {
| Self::Dense { .. } => {
if let Some(regex) = ®ex {
if regex.is_match(&format!("{}", coords))? {
continue;
}
} else { };
},
| Self::Sparse { .. } => {
if let Some(regex) = ®ex {
if !regex.is_match(&format!("{}", coords))? {
continue;
}
} else {
continue;
};
},
}
let mut env = HashMap::<String, String>::new();
for m in next {
if let Some(e) = &m.1.env {
env.extend(e.clone());
}
}
v.push(crate::plan::Invocation { env, coords });
}
Ok(v)
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub(crate) struct MatrixCell {
pub env: Option<HashMap<String, String>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case", deny_unknown_fields)]
pub(crate) struct Task {
pub script: String,
pub env: Option<HashMap<String, String>>,
pub shell: Option<Shell>,
pub workdir: Option<String>,
}