gremlin_client/
message.rs1use serde::{Deserialize as SerdeDeserialize, Deserializer};
2use serde_derive::{Deserialize, Serialize};
3use serde_json::Value;
4use uuid::Uuid;
5
6#[derive(Serialize)]
7#[serde(rename_all = "camelCase")]
8pub struct RequestIdV2 {
9 #[serde(rename = "@type")]
10 id_type: String,
11
12 #[serde(rename = "@value")]
13 value: Uuid,
14}
15
16#[derive(Serialize)]
17#[serde(rename_all = "camelCase", untagged)]
18pub enum Message<T> {
19 #[serde(rename_all = "camelCase")]
20 V1 {
21 request_id: Uuid,
22 op: String,
23 processor: String,
24 args: T,
25 },
26 #[serde(rename_all = "camelCase")]
27 V2 {
28 request_id: RequestIdV2,
29 op: String,
30 processor: String,
31 args: T,
32 },
33 #[serde(rename_all = "camelCase")]
34 V3 {
35 request_id: Uuid,
36 op: String,
37 processor: String,
38 args: T,
39 },
40}
41
42impl<T> Message<T> {
43 #[allow(dead_code)]
44 pub fn id(&self) -> &Uuid {
45 match self {
46 Message::V1 { request_id, .. } => request_id,
47 Message::V2 { request_id, .. } => &request_id.value,
48 Message::V3 { request_id, .. } => request_id,
49 }
50 }
51}
52#[derive(Debug, Deserialize)]
53#[serde(rename_all = "camelCase")]
54pub struct Response {
55 pub request_id: Uuid,
56 pub result: ResponseResult,
57 pub status: ReponseStatus,
58}
59
60#[derive(Debug, Deserialize)]
61pub struct ResponseResult {
62 pub data: Value,
63}
64
65#[derive(Debug, Deserialize)]
66pub struct ReponseStatus {
67 pub code: i16,
68 #[serde(default, deserialize_with = "map_null_to_default")]
70 pub message: String,
71}
72
73fn map_null_to_default<'de, D, T>(de: D) -> Result<T, D::Error>
74where
75 D: Deserializer<'de>,
76 T: Default + SerdeDeserialize<'de>,
77{
78 Option::<T>::deserialize(de).map(Option::unwrap_or_default)
79}
80
81pub fn message_with_args_v2<T>(op: String, processor: String, args: T) -> Message<T> {
82 message_with_args_and_uuid_v2(op, processor, Uuid::new_v4(), args)
83}
84
85pub fn message_with_args_and_uuid_v2<T>(
86 op: String,
87 processor: String,
88 id: Uuid,
89 args: T,
90) -> Message<T> {
91 Message::V2 {
92 request_id: RequestIdV2 {
93 id_type: "g:UUID".to_string(),
94 value: id,
95 },
96 op,
97 processor,
98 args,
99 }
100}
101
102pub fn message_with_args<T>(op: String, processor: String, args: T) -> Message<T> {
103 message_with_args_and_uuid(op, processor, Uuid::new_v4(), args)
104}
105
106pub fn message_with_args_and_uuid<T>(
107 op: String,
108 processor: String,
109 id: Uuid,
110 args: T,
111) -> Message<T> {
112 Message::V3 {
113 request_id: id,
114 op,
115 processor,
116 args,
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use crate::message::ReponseStatus;
123
124 #[test]
125 fn handle_no_response_status_message() {
126 let parsed: ReponseStatus =
127 serde_json::from_str(r#"{"code": 123}"#).expect("Failed to parse test message");
128 assert_eq!(123, parsed.code);
129 assert_eq!("", parsed.message);
130 }
131
132 #[test]
133 fn handle_null_response_status_message() {
134 let parsed: ReponseStatus = serde_json::from_str(r#"{"code": 123, "message": null}"#)
135 .expect("Failed to parse test message");
136 assert_eq!(123, parsed.code);
137 assert_eq!("", parsed.message);
138 }
139
140 #[test]
141 fn handle_response_status_message() {
142 let parsed: ReponseStatus =
143 serde_json::from_str(r#"{"code": 123, "message": "Hello World"}"#)
144 .expect("Failed to parse test message");
145 assert_eq!(123, parsed.code);
146 assert_eq!("Hello World", parsed.message);
147 }
148}