use serde_json::{Map, Value, json};
use super::{Deposit, InboxEntry};
pub(crate) fn reply(entries: &[InboxEntry]) -> Value {
json!({
"ok": true, "kind": "inbox",
"rows": Value::Array(entries.iter().map(entry_row).collect()),
})
}
fn entry_row(entry: &InboxEntry) -> Value {
let mut map = Map::new();
map.insert("name".to_owned(), json!(entry.name));
map.insert("raw".to_owned(), json!(String::from_utf8_lossy(&entry.raw)));
map.insert("deposit".to_owned(), deposit_value(&entry.deposit));
Value::Object(map)
}
fn deposit_value(deposit: &Deposit) -> Value {
let mut map = Map::new();
for (key, value) in [
("from", deposit.sender.as_ref()),
("from_name", deposit.from_name.as_ref()),
("deposited_at", deposit.deposited_at.as_ref()),
("terminal_ref", deposit.terminal_ref.as_ref()),
] {
if let Some(value) = value {
map.insert(key.to_owned(), json!(value));
}
}
if let Some(epitaph) = &deposit.epitaph {
map.insert("epitaph".to_owned(), json!(epitaph.label()));
}
map.insert("body".to_owned(), json!(deposit.body));
Value::Object(map)
}
pub(crate) fn entries_of(obj: &serde_json::Map<String, Value>) -> Result<Vec<InboxEntry>, String> {
use crate::boundary::codec::fields::list_of;
list_of(obj, "rows", entry_of)
}
fn entry_of(v: &Value) -> Result<InboxEntry, String> {
use crate::boundary::codec::fields::{bytes_of, str_of};
let o = v.as_object().ok_or("inbox row: not an object")?;
Ok(InboxEntry {
name: str_of(o, "name")?,
raw: bytes_of(o, "raw")?,
deposit: deposit_of(o.get("deposit").ok_or("inbox row: missing deposit")?)?,
})
}
fn deposit_of(v: &Value) -> Result<Deposit, String> {
use crate::boundary::codec::fields::{opt_str_of, str_of};
let o = v.as_object().ok_or("deposit: not an object")?;
Ok(Deposit {
sender: opt_str_of(o, "from")?,
from_name: opt_str_of(o, "from_name")?,
deposited_at: opt_str_of(o, "deposited_at")?,
epitaph: opt_str_of(o, "epitaph")?.map(|w| super::Epitaph::parse(&w)),
terminal_ref: opt_str_of(o, "terminal_ref")?,
body: str_of(o, "body")?,
})
}