use serde_json::{Map, Value, json};
use crate::boundary::codec::fields::{opt_str_of, str_of};
use crate::boundary::codec::{join_token, parse_join};
use crate::nav::BoundBall;
use super::board::decode::figure;
use super::board::figure_value;
pub(super) fn bound_ball(ball: &BoundBall) -> Value {
let mut map = Map::new();
map.insert("id".to_owned(), json!(ball.id));
if let Some(badge) = &ball.badge {
map.insert("badge".to_owned(), json!(badge));
}
map.insert("project".to_owned(), json!(ball.project));
map.insert("owner".to_owned(), json!(ball.owner));
map.insert("state".to_owned(), json!(join_token(ball.state)));
map.insert("spend".to_owned(), figure_value(&ball.spend));
Value::Object(map)
}
pub(super) fn bound_ball_of(v: &Value) -> Result<BoundBall, String> {
let o = v.as_object().ok_or("ball row: not an object")?;
Ok(BoundBall {
id: str_of(o, "id")?,
badge: opt_str_of(o, "badge")?,
project: str_of(o, "project")?,
owner: str_of(o, "owner")?,
state: parse_join(&str_of(o, "state")?)?,
spend: figure(o.get("spend").ok_or("ball row: missing spend")?)?,
})
}