use crate::boundary::codec::fields::str_of;
use crate::boundary::config::ConfigFile;
use crate::config_edit::branch::edit::EditOrigin;
use serde_json::{Map, Value, json};
pub(crate) fn encode_file(file: &ConfigFile) -> Value {
match file {
ConfigFile::Brazen { workspace } => {
json!({ "file": "brazen", "workspace": workspace })
}
ConfigFile::LitanyModels => json!({ "file": "litany-models" }),
ConfigFile::LitanyWorkflow { name } => {
json!({ "file": "litany-workflow", "name": name })
}
ConfigFile::Cadence => json!({ "file": "cadence" }),
ConfigFile::Branch {
workspace,
lineage,
origin,
path,
} => {
let mut map = Map::new();
map.insert("file".to_owned(), json!("branch"));
map.insert("workspace".to_owned(), Value::String(workspace.clone()));
map.insert("lineage".to_owned(), json!(lineage));
map.insert("path".to_owned(), json!(path));
for (k, v) in origin_fields(origin) {
map.insert(k, v);
}
Value::Object(map)
}
}
}
const PLACE: &str = "the config family carries its parameters INSIDE target";
fn field_of(obj: &Map<String, Value>, file: &str, key: &str) -> Result<String, String> {
str_of(obj, key).map_err(|why| format!("config: target for file {file:?}: {why} — {PLACE}"))
}
pub(crate) fn decode_file(v: &Value) -> Result<ConfigFile, String> {
let obj = v.as_object().ok_or("config: target is not an object")?;
let file = str_of(obj, "file")?;
match file.as_str() {
"brazen" => Ok(ConfigFile::Brazen {
workspace: field_of(obj, &file, "workspace")?,
}),
"litany-models" => Ok(ConfigFile::LitanyModels),
"litany-workflow" => Ok(ConfigFile::LitanyWorkflow {
name: field_of(obj, &file, "name")?,
}),
"cadence" => Ok(ConfigFile::Cadence),
"branch" => Ok(ConfigFile::Branch {
workspace: field_of(obj, &file, "workspace")?,
lineage: field_of(obj, &file, "lineage")?,
origin: decode_origin(obj, &file)?,
path: field_of(obj, &file, "path")?,
}),
other => Err(format!("config: unknown target file {other:?}")),
}
}
fn origin_fields(origin: &EditOrigin) -> Vec<(String, Value)> {
match origin {
EditOrigin::Advance => vec![("origin".to_owned(), json!("advance"))],
EditOrigin::Fork { source } => vec![
("origin".to_owned(), json!("fork")),
("source".to_owned(), json!(source)),
],
EditOrigin::Orphan => vec![("origin".to_owned(), json!("orphan"))],
}
}
fn decode_origin(obj: &Map<String, Value>, file: &str) -> Result<EditOrigin, String> {
match field_of(obj, file, "origin")?.as_str() {
"advance" => Ok(EditOrigin::Advance),
"fork" => Ok(EditOrigin::Fork {
source: field_of(obj, file, "source")?,
}),
"orphan" => Ok(EditOrigin::Orphan),
other => Err(format!("config: unknown origin {other:?}")),
}
}
#[cfg(test)]
mod tests;