use crate::{
GraveGoods, Key, LastWill, Path, ProtocolVersions, RequestPattern, TransactionId, Value,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ClientMessage {
HandshakeRequest(HandshakeRequest),
Get(Get),
PGet(PGet),
Set(Set),
Publish(Publish),
Subscribe(Subscribe),
PSubscribe(PSubscribe),
Export(Export),
Import(Import),
Unsubscribe(Unsubscribe),
Delete(Delete),
PDelete(PDelete),
Ls(Ls),
SubscribeLs(SubscribeLs),
UnsubscribeLs(UnsubscribeLs),
}
impl ClientMessage {
pub fn transaction_id(&self) -> TransactionId {
match self {
ClientMessage::HandshakeRequest(_) => 0,
ClientMessage::Get(m) => m.transaction_id,
ClientMessage::PGet(m) => m.transaction_id,
ClientMessage::Set(m) => m.transaction_id,
ClientMessage::Publish(m) => m.transaction_id,
ClientMessage::Subscribe(m) => m.transaction_id,
ClientMessage::PSubscribe(m) => m.transaction_id,
ClientMessage::Export(m) => m.transaction_id,
ClientMessage::Import(m) => m.transaction_id,
ClientMessage::Unsubscribe(m) => m.transaction_id,
ClientMessage::Delete(m) => m.transaction_id,
ClientMessage::PDelete(m) => m.transaction_id,
ClientMessage::Ls(m) => m.transaction_id,
ClientMessage::SubscribeLs(m) => m.transaction_id,
ClientMessage::UnsubscribeLs(m) => m.transaction_id,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HandshakeRequest {
pub supported_protocol_versions: ProtocolVersions,
pub last_will: LastWill,
pub grave_goods: GraveGoods,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Get {
pub transaction_id: TransactionId,
pub key: Key,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PGet {
pub transaction_id: TransactionId,
pub request_pattern: RequestPattern,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Set {
pub transaction_id: TransactionId,
pub key: Key,
pub value: Value,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Publish {
pub transaction_id: TransactionId,
pub key: Key,
pub value: Value,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Subscribe {
pub transaction_id: TransactionId,
pub key: RequestPattern,
pub unique: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PSubscribe {
pub transaction_id: TransactionId,
pub request_pattern: RequestPattern,
pub unique: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Export {
pub transaction_id: TransactionId,
pub path: Path,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Import {
pub transaction_id: TransactionId,
pub path: Path,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Unsubscribe {
pub transaction_id: TransactionId,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Delete {
pub transaction_id: TransactionId,
pub key: Key,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PDelete {
pub transaction_id: TransactionId,
pub request_pattern: RequestPattern,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Ls {
pub transaction_id: TransactionId,
pub parent: Option<Key>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SubscribeLs {
pub transaction_id: TransactionId,
pub parent: Option<Key>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UnsubscribeLs {
pub transaction_id: TransactionId,
}
#[cfg(test)]
mod test {
use super::*;
use crate::ProtocolVersion;
use serde_json::json;
#[test]
fn handshake_request_is_serialized_correctly() {
let msg = ClientMessage::HandshakeRequest(HandshakeRequest {
grave_goods: vec!["delete/this/stuff/#".to_owned()],
last_will: vec![("set/this", json!("to this value")).into()],
supported_protocol_versions: vec![ProtocolVersion { major: 0, minor: 1 }],
});
let json = r#"{"handshakeRequest":{"supportedProtocolVersions":[{"major":0,"minor":1}],"lastWill":[{"key":"set/this","value":"to this value"}],"graveGoods":["delete/this/stuff/#"]}}"#;
assert_eq!(&serde_json::to_string(&msg).unwrap(), json);
}
#[test]
fn handshake_request_is_deserialized_correctly() {
let msg = ClientMessage::HandshakeRequest(HandshakeRequest {
grave_goods: vec!["delete/this/stuff/#".to_owned()],
last_will: vec![("set/this", json!("to this value")).into()],
supported_protocol_versions: vec![ProtocolVersion { major: 0, minor: 1 }],
});
let json = r#"{
"handshakeRequest": {
"supportedProtocolVersions": [{ "major": 0, "minor": 1 }],
"lastWill": [{ "key": "set/this", "value": "to this value" }],
"graveGoods": ["delete/this/stuff/#"]
}
}"#;
assert_eq!(serde_json::from_str::<ClientMessage>(&json).unwrap(), msg);
}
#[test]
fn set_is_deserialized_correctly() {
let json = r#"{"set": {"transactionId": 2, "key": "hello/world", "value": { "this value": "is a ", "complex": "JSON object"}}}"#;
let msg = serde_json::from_str::<ClientMessage>(&json).unwrap();
assert_eq!(
msg,
ClientMessage::Set(Set {
transaction_id: 2,
key: "hello/world".to_owned(),
value: json!({ "this value": "is a ", "complex": "JSON object"}),
})
);
}
}