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