use serde_json::{Map, Value, json};
use super::{ChildCard, Notch, Rail};
pub(crate) fn reply(rail: &Rail) -> Value {
json!({
"ok": true, "kind": "rail",
"rows": Value::Array(rail.notches.iter().map(notch_row).collect()),
"cards": Value::Array(rail.cards.iter().map(card_row).collect()),
})
}
fn notch_row(notch: &Notch) -> Value {
let mut map = Map::new();
map.insert("seq".to_owned(), json!(notch.seq));
map.insert("budget".to_owned(), json!(notch.budget));
crate::boundary::reply::cost::opt_cost("cost", notch.cost.as_ref(), &mut map);
if let Some(commit) = ¬ch.commit {
map.insert("commit".to_owned(), json!(commit));
map.insert("short".to_owned(), json!(notch.short()));
}
if let Some(place) = ¬ch.place {
map.insert("row".to_owned(), json!(place.row));
map.insert("cut".to_owned(), json!(place.cut));
}
Value::Object(map)
}
fn card_row(card: &ChildCard) -> Value {
let mut map = Map::new();
map.insert("agent".to_owned(), json!(card.agent_id));
map.insert("name".to_owned(), json!(card.name));
map.insert("fork".to_owned(), json!(card.fork));
map.insert(
"state".to_owned(),
json!(crate::boundary::reply::rows::state_token(card.state)),
);
map.insert("tokens".to_owned(), json!(card.tokens));
map.insert("notch".to_owned(), json!(card.provenance_notch));
if let Some(tail) = &card.tail {
map.insert("tail".to_owned(), json!(tail));
}
Value::Object(map)
}
pub(crate) fn rail_of(obj: &serde_json::Map<String, Value>) -> Result<Rail, String> {
use crate::boundary::codec::fields::list_of;
Ok(Rail {
notches: list_of(obj, "rows", notch_of)?,
cards: list_of(obj, "cards", card_of)?,
})
}
fn notch_of(v: &Value) -> Result<Notch, String> {
use crate::boundary::codec::fields::{opt_str_of, opt_val, str_of, u64_of, usize_of};
let o = v.as_object().ok_or("notch: not an object")?;
let place = match opt_str_of(o, "row")? {
None => None,
Some(row) => Some(super::Place {
row,
cut: usize_of(o, "cut")?,
}),
};
Ok(Notch {
seq: str_of(o, "seq")?,
commit: opt_str_of(o, "commit")?,
budget: u64_of(o, "budget")?,
cost: opt_val(o, "cost", crate::boundary::reply::cost::cost_of)?,
place,
})
}
fn card_of(v: &Value) -> Result<ChildCard, String> {
use crate::boundary::codec::fields::{opt_str_of, str_of, u64_of, usize_of};
let o = v.as_object().ok_or("card: not an object")?;
Ok(ChildCard {
agent_id: str_of(o, "agent")?,
name: str_of(o, "name")?,
fork: str_of(o, "fork")?,
state: crate::boundary::reply::rows::decode::state_of(o)?,
tokens: u64_of(o, "tokens")?,
tail: opt_str_of(o, "tail")?,
provenance_notch: usize_of(o, "notch")?,
})
}