1use crate::{
21 AuthToken, Key, LiveOnlyFlag, ProtocolVersionSegment, RequestPattern, TransactionId,
22 UniqueFlag, Value,
23};
24use serde::{Deserialize, Serialize};
25
26#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub enum ClientMessage {
29 ProtocolSwitchRequest(ProtocolSwitchRequest),
30 AuthorizationRequest(AuthorizationRequest),
31 Get(Get),
32 CGet(Get),
33 PGet(PGet),
34 Set(Set),
35 CSet(CSet),
36 SPubInit(SPubInit),
37 SPub(SPub),
38 Publish(Publish),
39 Subscribe(Subscribe),
40 PSubscribe(PSubscribe),
41 Unsubscribe(Unsubscribe),
42 Delete(Delete),
43 PDelete(PDelete),
44 Ls(Ls),
45 PLs(PLs),
46 SubscribeLs(SubscribeLs),
47 UnsubscribeLs(UnsubscribeLs),
48 Lock(Lock),
49 ReleaseLock(Lock),
50 Transform(Transform),
51}
52
53impl ClientMessage {
54 pub fn transaction_id(&self) -> Option<TransactionId> {
55 match self {
56 ClientMessage::ProtocolSwitchRequest(_) | ClientMessage::AuthorizationRequest(_) => {
57 Some(0)
58 }
59 ClientMessage::Get(m) | ClientMessage::CGet(m) => Some(m.transaction_id),
60 ClientMessage::PGet(m) => Some(m.transaction_id),
61 ClientMessage::Set(m) => Some(m.transaction_id),
62 ClientMessage::CSet(m) => Some(m.transaction_id),
63 ClientMessage::SPubInit(m) => Some(m.transaction_id),
64 ClientMessage::SPub(m) => Some(m.transaction_id),
65 ClientMessage::Publish(m) => Some(m.transaction_id),
66 ClientMessage::Subscribe(m) => Some(m.transaction_id),
67 ClientMessage::PSubscribe(m) => Some(m.transaction_id),
68 ClientMessage::Unsubscribe(m) => Some(m.transaction_id),
69 ClientMessage::Delete(m) => Some(m.transaction_id),
70 ClientMessage::PDelete(m) => Some(m.transaction_id),
71 ClientMessage::Ls(m) => Some(m.transaction_id),
72 ClientMessage::PLs(m) => Some(m.transaction_id),
73 ClientMessage::SubscribeLs(m) => Some(m.transaction_id),
74 ClientMessage::UnsubscribeLs(m) => Some(m.transaction_id),
75 ClientMessage::Lock(m) => Some(m.transaction_id),
76 ClientMessage::ReleaseLock(m) => Some(m.transaction_id),
77 ClientMessage::Transform(m) => Some(m.transaction_id),
78 }
79 }
80}
81#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct ProtocolSwitchRequest {
84 pub version: ProtocolVersionSegment,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88#[serde(rename_all = "camelCase")]
89pub struct AuthorizationRequest {
90 pub auth_token: AuthToken,
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct Get {
96 pub transaction_id: TransactionId,
97 pub key: Key,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
101#[serde(rename_all = "camelCase")]
102pub struct PGet {
103 pub transaction_id: TransactionId,
104 pub request_pattern: RequestPattern,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108#[serde(rename_all = "camelCase")]
109pub struct Set {
110 pub transaction_id: TransactionId,
111 pub key: Key,
112 pub value: Value,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
116#[serde(rename_all = "camelCase")]
117pub struct CSet {
118 pub transaction_id: TransactionId,
119 pub key: Key,
120 pub value: Value,
121 pub version: u64,
122}
123
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct SPubInit {
127 pub transaction_id: TransactionId,
128 pub key: Key,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
132#[serde(rename_all = "camelCase")]
133pub struct SPub {
134 pub transaction_id: TransactionId,
135 pub value: Value,
136}
137
138#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
139#[serde(rename_all = "camelCase")]
140pub struct Publish {
141 pub transaction_id: TransactionId,
142 pub key: Key,
143 pub value: Value,
144}
145#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct Subscribe {
148 pub transaction_id: TransactionId,
149 pub key: RequestPattern,
150 pub unique: UniqueFlag,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub live_only: Option<LiveOnlyFlag>,
153}
154
155#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
156#[serde(rename_all = "camelCase")]
157pub struct PSubscribe {
158 pub transaction_id: TransactionId,
159 pub request_pattern: RequestPattern,
160 pub unique: UniqueFlag,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub aggregate_events: Option<u64>,
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub live_only: Option<LiveOnlyFlag>,
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
168#[serde(rename_all = "camelCase")]
169pub struct Unsubscribe {
170 pub transaction_id: TransactionId,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
174#[serde(rename_all = "camelCase")]
175pub struct Delete {
176 pub transaction_id: TransactionId,
177 pub key: Key,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
181#[serde(rename_all = "camelCase")]
182pub struct PDelete {
183 pub transaction_id: TransactionId,
184 pub request_pattern: RequestPattern,
185 pub quiet: Option<bool>,
186}
187
188#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
189#[serde(rename_all = "camelCase")]
190pub struct Ls {
191 pub transaction_id: TransactionId,
192 pub parent: Option<Key>,
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct PLs {
198 pub transaction_id: TransactionId,
199 pub parent_pattern: Option<RequestPattern>,
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203#[serde(rename_all = "camelCase")]
204pub struct SubscribeLs {
205 pub transaction_id: TransactionId,
206 pub parent: Option<Key>,
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
210#[serde(rename_all = "camelCase")]
211pub struct UnsubscribeLs {
212 pub transaction_id: TransactionId,
213}
214
215#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
216#[serde(rename_all = "camelCase")]
217pub struct Lock {
218 pub transaction_id: TransactionId,
219 pub key: Key,
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
223#[serde(rename_all = "camelCase")]
224pub struct Transform {
225 pub transaction_id: TransactionId,
226 pub key: Key,
227 pub template: Value,
228}
229
230#[cfg(test)]
231mod test {
232
233 use super::*;
234 use serde_json::json;
235
236 #[test]
237 fn auth_request_is_serialized_correctly() {
238 let msg = ClientMessage::AuthorizationRequest(AuthorizationRequest {
239 auth_token: "123456".to_owned(),
240 });
241
242 let json = r#"{"authorizationRequest":{"authToken":"123456"}}"#;
243
244 assert_eq!(&serde_json::to_string(&msg).unwrap(), json);
245 }
246
247 #[test]
248 fn auth_request_is_deserialized_correctly() {
249 let msg = ClientMessage::AuthorizationRequest(AuthorizationRequest {
250 auth_token: "123456".to_owned(),
251 });
252
253 let json = r#"{
254 "authorizationRequest": {
255 "authToken": "123456"
256 }
257 }"#;
258
259 assert_eq!(serde_json::from_str::<ClientMessage>(json).unwrap(), msg);
260 }
261
262 #[test]
263 fn set_is_deserialized_correctly() {
264 let json = r#"{"set": {"transactionId": 2, "key": "hello/world", "value": { "this value": "is a ", "complex": "JSON object"}}}"#;
265 let msg = serde_json::from_str::<ClientMessage>(json).unwrap();
266 assert_eq!(
267 msg,
268 ClientMessage::Set(Set {
269 transaction_id: 2,
270 key: "hello/world".to_owned(),
271 value: json!({ "this value": "is a ", "complex": "JSON object"}),
272 })
273 );
274 }
275
276 #[test]
277 fn psubscribe_without_aggregation_is_serialized_correctly() {
278 let msg = ClientMessage::PSubscribe(PSubscribe {
279 transaction_id: 1,
280 request_pattern: "hello/world".to_owned(),
281 unique: true,
282 aggregate_events: None,
283 live_only: None,
284 });
285
286 let json = serde_json::to_string(&msg).unwrap();
287 assert_eq!(
288 json,
289 r#"{"pSubscribe":{"transactionId":1,"requestPattern":"hello/world","unique":true}}"#
290 );
291 }
292
293 #[test]
294 fn psubscribe_with_aggregation_is_serialized_correctly() {
295 let msg = ClientMessage::PSubscribe(PSubscribe {
296 transaction_id: 1,
297 request_pattern: "hello/world".to_owned(),
298 unique: true,
299 aggregate_events: Some(10),
300 live_only: Some(true),
301 });
302
303 let json = serde_json::to_string(&msg).unwrap();
304 assert_eq!(
305 json,
306 r#"{"pSubscribe":{"transactionId":1,"requestPattern":"hello/world","unique":true,"aggregateEvents":10,"liveOnly":true}}"#
307 );
308 }
309
310 #[test]
311 fn psubscribe_without_aggregation_is_deserialized_correctly() {
312 let json =
313 r#"{"pSubscribe":{"transactionId":1,"requestPattern":"hello/world","unique":true}}"#;
314 let msg: ClientMessage = serde_json::from_str(json).unwrap();
315
316 assert_eq!(
317 msg,
318 ClientMessage::PSubscribe(PSubscribe {
319 transaction_id: 1,
320 request_pattern: "hello/world".to_owned(),
321 unique: true,
322 aggregate_events: None,
323 live_only: None,
324 })
325 );
326 }
327
328 #[test]
329 fn psubscribe_with_aggregation_is_deserialized_correctly() {
330 let json = r#"{"pSubscribe":{"transactionId":1,"requestPattern":"hello/world","unique":true,"aggregateEvents":10,"liveOnly":false}}"#;
331 let msg: ClientMessage = serde_json::from_str(json).unwrap();
332
333 assert_eq!(
334 msg,
335 ClientMessage::PSubscribe(PSubscribe {
336 transaction_id: 1,
337 request_pattern: "hello/world".to_owned(),
338 unique: true,
339 aggregate_events: Some(10),
340 live_only: Some(false),
341 })
342 );
343 }
344
345 #[test]
346 fn transform_is_serialized_correctly() {
347 let msg = ClientMessage::Transform(Transform {
348 transaction_id: 123,
349 key: "test/transformed/key".to_owned(),
350 template: json!({
351 "name": "@some/person/name",
352 "email": "@some/person/email",
353 "phone": "@some/person/phone",
354 "meta": {
355 "nested": "@some/completely/unrelated/key",
356 "info": "this is not a key reference and will remain in the transformed state"
357 }
358 }),
359 });
360
361 let json = serde_json::to_string(&msg).unwrap();
362 assert_eq!(
363 json,
364 r#"{"transform":{"transactionId":123,"key":"test/transformed/key","template":{"email":"@some/person/email","meta":{"info":"this is not a key reference and will remain in the transformed state","nested":"@some/completely/unrelated/key"},"name":"@some/person/name","phone":"@some/person/phone"}}}"#
365 );
366 }
367
368 #[test]
369 fn transform_is_deserialized_correctly() {
370 let json = r#"{
371 "transform": {
372 "transactionId": 123,
373 "key": "test/transformed/key",
374 "template": {
375 "name": "@some/person/name",
376 "email": "@some/person/email",
377 "phone": "@some/person/phone",
378 "meta": {
379 "nested": "@some/completely/unrelated/key",
380 "info": "this is not a key reference and will remain in the transformed state"
381 }
382 }
383 }
384 }
385 "#;
386 let msg: ClientMessage = serde_json::from_str(json).unwrap();
387
388 assert_eq!(
389 msg,
390 ClientMessage::Transform(Transform {
391 transaction_id: 123,
392 key: "test/transformed/key".to_owned(),
393 template: json!({
394 "name": "@some/person/name",
395 "email": "@some/person/email",
396 "phone": "@some/person/phone",
397 "meta": {
398 "nested": "@some/completely/unrelated/key",
399 "info": "this is not a key reference and will remain in the transformed state"
400 }
401 }),
402 })
403 );
404 }
405
406 #[test]
407 fn spub_init_is_deserialized_correctly() {
408 let json = r#"{"sPubInit": {"transactionId": 2, "key": "hello/world"}}"#;
409 let expected = ClientMessage::SPubInit(SPubInit {
410 transaction_id: 2,
411 key: "hello/world".into(),
412 });
413 assert_eq!(
414 serde_json::from_str::<ClientMessage>(json).unwrap(),
415 expected
416 );
417 }
418
419 #[test]
420 fn spub_is_deserialized_correctly() {
421 let json = r#"{"sPub": {"transactionId": 2, "value": 123}}"#;
422 let expected = ClientMessage::SPub(SPub {
423 transaction_id: 2,
424 value: json!(123),
425 });
426 assert_eq!(
427 serde_json::from_str::<ClientMessage>(json).unwrap(),
428 expected
429 );
430 }
431
432 #[test]
433 fn spub_init_is_serialized_correctly() {
434 let json = r#"{"sPubInit":{"transactionId":2,"key":"hello/world"}}"#;
435 let expected = SPubInit {
436 transaction_id: 2,
437 key: "hello/world".into(),
438 };
439 assert_eq!(
440 &serde_json::to_string(&ClientMessage::SPubInit(expected)).unwrap(),
441 json
442 );
443 }
444
445 #[test]
446 fn spub_is_serialized_correctly() {
447 let json = r#"{"sPub":{"transactionId":2,"value":123}}"#;
448 let expected = SPub {
449 transaction_id: 2,
450 value: json!(123),
451 };
452 assert_eq!(
453 &serde_json::to_string(&ClientMessage::SPub(expected)).unwrap(),
454 json
455 );
456 }
457}