use super::PartyId;
use serde::{Deserialize, Serialize};
pub type BrokerResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct JsonMessage {
#[serde(rename = "type")]
pub typ: String,
#[serde(default)]
pub from: Option<PartyId>,
#[serde(default)]
pub to: Option<PartyId>,
#[serde(default)]
pub data: serde_json::Value,
}
pub fn json_get<T: for<'de> Deserialize<'de>>(msg: &JsonMessage) -> Result<T, serde_json::Error> {
T::deserialize(&msg.data)
}
pub fn json_wrap<T: Serialize>(
typ: impl Into<String>,
data: &T,
from: Option<PartyId>,
to: Option<PartyId>,
) -> Result<JsonMessage, serde_json::Error> {
Ok(JsonMessage {
typ: typ.into(),
from,
to,
data: serde_json::to_value(data)?,
})
}
pub trait MessageReceiver {
fn receive(&self, msg: &JsonMessage) -> BrokerResult;
}
pub trait MessageBroker: MessageReceiver {
fn connect(&self, typ: &str, dest: std::sync::Arc<dyn MessageReceiver + Send + Sync>);
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Payload {
round: u32,
commitment: String,
}
#[test]
fn wrap_then_get_roundtrips() {
let p = Payload {
round: 1,
commitment: "abc".into(),
};
let msg = json_wrap("keygen.r1", &p, None, None).unwrap();
assert_eq!(msg.typ, "keygen.r1");
let back: Payload = json_get(&msg).unwrap();
assert_eq!(back, p);
}
#[test]
fn json_field_names_match_go() {
let from = PartyId::new("1", "P[1]", vec![1]);
let msg = json_wrap("t", &42u32, Some(from), None).unwrap();
let v = serde_json::to_value(&msg).unwrap();
let obj = v.as_object().unwrap();
assert!(obj.contains_key("type"));
assert!(obj.contains_key("from"));
assert!(obj.contains_key("to"));
assert!(obj.contains_key("data"));
assert_eq!(v["data"], 42);
assert_eq!(v["to"], serde_json::Value::Null);
}
}