use crate::reconcile::Patch;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum RemoteMessage {
InitialTree(InitialTree),
Patch(PatchStream),
DispatchAction {
module: String,
action: String,
payload: Option<serde_json::Value>,
},
StateUpdate {
module: String,
state: serde_json::Value,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InitialTree {
pub module: String,
pub state: serde_json::Value,
pub patches: Vec<Patch>,
pub revision: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub hash: Option<String>,
}
impl InitialTree {
pub fn new(module: String, state: serde_json::Value, patches: Vec<Patch>) -> Self {
Self {
module,
state,
patches,
revision: 0,
hash: None,
}
}
pub fn with_hash(mut self, hash: String) -> Self {
self.hash = Some(hash);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatchStream {
pub module: String,
pub patches: Vec<Patch>,
pub revision: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub hash: Option<String>,
}
impl PatchStream {
pub fn new(module: String, patches: Vec<Patch>, revision: u64) -> Self {
Self {
module,
patches,
revision,
hash: None,
}
}
pub fn with_hash(mut self, hash: String) -> Self {
self.hash = Some(hash);
self
}
}
pub fn serialize_message(message: &RemoteMessage) -> Result<String, serde_json::Error> {
serde_json::to_string(message)
}
pub fn deserialize_message(json: &str) -> Result<RemoteMessage, serde_json::Error> {
serde_json::from_str(json)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialize_initial_tree() {
let initial = InitialTree::new(
"TestModule".to_string(),
serde_json::json!({"count": 0}),
vec![],
);
let message = RemoteMessage::InitialTree(initial);
let json = serialize_message(&message).unwrap();
assert!(json.contains("initialTree"));
assert!(json.contains("TestModule"));
}
#[test]
fn test_roundtrip() {
let message = RemoteMessage::DispatchAction {
module: "Test".to_string(),
action: "increment".to_string(),
payload: Some(serde_json::json!({"amount": 1})),
};
let json = serialize_message(&message).unwrap();
let deserialized = deserialize_message(&json).unwrap();
match deserialized {
RemoteMessage::DispatchAction { module, action, .. } => {
assert_eq!(module, "Test");
assert_eq!(action, "increment");
}
_ => panic!("Wrong message type"),
}
}
}