use serde_json::{Map, Value, json};
use super::{ProposalRow, ProposalView};
use crate::boundary::codec::fields::{bool_of, list_of, opt_str_of, str_of, strings_of};
pub const KIND: &str = "proposals";
pub fn reply(view: &ProposalView) -> Value {
let mut map = Map::new();
map.insert("ok".to_owned(), json!(true));
map.insert("kind".to_owned(), json!(KIND));
map.insert(
"rows".to_owned(),
Value::Array(view.rows.iter().map(row).collect()),
);
if let Some(whole) = &view.whole {
map.insert("whole".to_owned(), json!(whole));
}
Value::Object(map)
}
fn row(row: &ProposalRow) -> Value {
json!({
"id": row.id,
"lineages": row.lineages,
"parent": row.parent,
"fresh": row.fresh,
"diffstat": row.diffstat,
"subject": row.subject,
})
}
pub fn view_of(o: &Map<String, Value>) -> Result<ProposalView, String> {
Ok(ProposalView {
rows: list_of(o, "rows", row_of)?,
whole: opt_str_of(o, "whole")?,
})
}
fn row_of(v: &Value) -> Result<ProposalRow, String> {
let o = v.as_object().ok_or("proposal row: not an object")?;
Ok(ProposalRow {
id: str_of(o, "id")?,
lineages: strings_of(o, "lineages")?,
parent: str_of(o, "parent")?,
fresh: bool_of(o, "fresh")?,
diffstat: str_of(o, "diffstat")?,
subject: str_of(o, "subject")?,
})
}