use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use serde_repr::{Deserialize_repr, Serialize_repr}; pub type Payload = Map; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { src: String, dest: String, body: Body, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Body { #[serde(rename = "type")] pub typ: String, #[serde(default, skip_serializing_if = "u64_zero_by_ref")] pub msg_id: u64, #[serde(default, skip_serializing_if = "u64_zero_by_ref")] pub in_reply_to: u64, #[serde(flatten)] pub payload: Payload, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum ErrorCode { Definite(DefiniteError), Indefinite(IndefiniteError), } #[derive(Debug, Clone, Serialize_repr, Deserialize_repr)] #[repr(u64)] pub enum DefiniteError { NodeNotFound = 2, NotSupported = 10, TemporarilyUnavailable = 11, MalformedRequest = 12, Abort = 14, KeyNotFound = 20, KeyAlreadyExists = 21, PreconditionFailed = 22, TxnConflict = 30, } #[derive(Debug, Clone, Serialize_repr, Deserialize_repr)] #[repr(u64)] pub enum IndefiniteError { Timeout = 0, Crash = 13, } pub fn init_ok(msg_id: u64, in_reply_to: u64) -> Body { Body { typ: "init_ok".to_string(), msg_id, in_reply_to, payload: Payload::new(), } } pub fn error(msg_id: u64, in_reply_to: u64, code: ErrorCode, text: Option<&str>) -> Body { Body { typ: "error".to_string(), msg_id, in_reply_to, payload: [ ("code".to_string(), serde_json::to_value(code).unwrap()), ("text".to_string(), serde_json::to_value(text).unwrap()), ] .into_iter() .collect(), } } #[allow(clippy::trivially_copy_pass_by_ref)] fn u64_zero_by_ref(num: &u64) -> bool { *num == 0 } #[cfg(test)] mod test { use super::*; #[test] fn error_codes() { let ec = ErrorCode::Definite(DefiniteError::Abort); let e = serde_json::to_string(&ec).unwrap(); assert_eq!(&e, "14"); } }