chatty-catties/nebkor-maelstrom/src/protocol.rs

117 lines
2.6 KiB
Rust
Raw Normal View History

2024-05-19 22:19:43 +00:00
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use serde_repr::{Deserialize_repr, Serialize_repr};
pub type Payload = Map<String, Value>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub src: String,
pub dest: String,
pub body: Body,
2024-05-19 22:19:43 +00:00
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
2024-05-19 22:19:43 +00:00
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,
}
impl Body {
pub fn from_type(typ: &str) -> Self {
Body {
typ: typ.to_string(),
..Default::default()
}
}
pub fn with_msg_id(self, msg_id: u64) -> Self {
let mut b = self;
b.msg_id = msg_id;
b
}
pub fn with_in_reply_to(self, in_reply_to: u64) -> Self {
let mut b = self;
b.in_reply_to = in_reply_to;
b
}
pub fn with_payload(self, payload: Payload) -> Self {
let mut b = self;
b.payload = payload;
b
}
}
pub fn init_ok(msg_id: u64, in_reply_to: u64) -> Body {
Body::from_type("init_ok")
.with_msg_id(msg_id)
.with_in_reply_to(in_reply_to)
}
2024-05-19 22:19:43 +00:00
#[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 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");
}
}