1use bytes::Bytes;
2
3#[derive(Debug, PartialEq, Eq, Clone)]
11pub enum Payload {
12 Binary(Bytes, Option<i32>),
13 Text(Vec<serde_json::Value>, Option<i32>),
14 #[deprecated = "Use `Payload::Text` instead. Continue existing behavior with: Payload::from(String)"]
15 String(String, Option<i32>),
17}
18
19impl Payload {
20 pub(crate) fn string_to_value(string: String) -> serde_json::Value {
21 if let Ok(value) = serde_json::from_str::<serde_json::Value>(&string) {
22 value
23 } else {
24 serde_json::Value::String(string)
25 }
26 }
27}
28
29impl From<&str> for Payload {
30 fn from(string: &str) -> Self {
31 Payload::from(string.to_owned())
32 }
33}
34
35impl Payload {
36 pub fn with_ack_id<T: Into<Self>>(payload: T, ack_id: i32) -> Self {
38 #[allow(deprecated)]
39 match payload.into() {
40 Payload::Binary(data, _) => Payload::Binary(data, Some(ack_id)),
41 Payload::Text(data, _) => Payload::Text(data, Some(ack_id)),
42 Payload::String(data, _) => Payload::String(data, Some(ack_id)),
43 }
44 }
45
46 pub fn ack_id(&self) -> Option<i32> {
48 #[allow(deprecated)]
49 match self {
50 Payload::Binary(_, ack_id) => *ack_id,
51 Payload::Text(_, ack_id) => *ack_id,
52 Payload::String(_, ack_id) => *ack_id,
53 }
54 }
55
56 pub fn set_ack_id(&mut self, ack_id: Option<i32>) {
58 #[allow(deprecated)]
59 match self {
60 Payload::Binary(_, id) => *id = ack_id,
61 Payload::Text(_, id) => *id = ack_id,
62 Payload::String(_, id) => *id = ack_id,
63 }
64 }
65
66 pub fn data(&self) -> PayloadData<'_> {
68 #[allow(deprecated)]
69 match self {
70 Payload::Binary(data, _) => PayloadData::Binary(data),
71 Payload::Text(data, _) => PayloadData::Text(data),
72 Payload::String(data, _) => PayloadData::String(data),
73 }
74 }
75}
76
77#[derive(Debug, PartialEq, Eq, Clone)]
79pub enum PayloadData<'a> {
80 Binary(&'a Bytes),
81 Text(&'a Vec<serde_json::Value>),
82 String(&'a String),
83}
84
85impl From<String> for Payload {
86 fn from(string: String) -> Self {
87 Self::Text(vec![Payload::string_to_value(string)], None)
88 }
89}
90
91impl From<Vec<String>> for Payload {
92 fn from(arr: Vec<String>) -> Self {
93 Self::Text(
94 arr.into_iter().map(Payload::string_to_value).collect(),
95 None,
96 )
97 }
98}
99
100impl From<Vec<serde_json::Value>> for Payload {
101 fn from(values: Vec<serde_json::Value>) -> Self {
102 Self::Text(values, None)
103 }
104}
105
106impl From<serde_json::Value> for Payload {
107 fn from(value: serde_json::Value) -> Self {
108 Self::Text(vec![value], None)
109 }
110}
111
112impl From<Vec<u8>> for Payload {
113 fn from(val: Vec<u8>) -> Self {
114 Self::Binary(Bytes::from(val), None)
115 }
116}
117
118impl From<&'static [u8]> for Payload {
119 fn from(val: &'static [u8]) -> Self {
120 Self::Binary(Bytes::from_static(val), None)
121 }
122}
123
124impl From<Bytes> for Payload {
125 fn from(bytes: Bytes) -> Self {
126 Self::Binary(bytes, None)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use serde_json::json;
133
134 use super::*;
135
136 #[test]
137 fn test_from_string() {
138 let sut = Payload::from("foo ™");
139
140 assert_eq!(
141 Payload::Text(vec![serde_json::Value::String(String::from("foo ™"))], None),
142 sut
143 );
144
145 let sut = Payload::from(String::from("foo ™"));
146 assert_eq!(
147 Payload::Text(vec![serde_json::Value::String(String::from("foo ™"))], None),
148 sut
149 );
150
151 let sut = Payload::from(json!("foo ™"));
152 assert_eq!(
153 Payload::Text(vec![serde_json::Value::String(String::from("foo ™"))], None),
154 sut
155 );
156 }
157
158 #[test]
159 fn test_from_multiple_strings() {
160 let input = vec![
161 "one".to_owned(),
162 "two".to_owned(),
163 json!(["foo", "bar"]).to_string(),
164 ];
165
166 assert_eq!(
167 Payload::Text(
168 vec![
169 serde_json::Value::String(String::from("one")),
170 serde_json::Value::String(String::from("two")),
171 json!(["foo", "bar"])
172 ],
173 None
174 ),
175 Payload::from(input)
176 );
177 }
178
179 #[test]
180 fn test_from_multiple_json() {
181 let input = vec![json!({"foo": "bar"}), json!("foo"), json!(["foo", "bar"])];
182
183 assert_eq!(
184 Payload::Text(input.clone(), None),
185 Payload::from(input.clone())
186 );
187 }
188
189 #[test]
190 fn test_from_json() {
191 let json = json!({
192 "foo": "bar"
193 });
194 let sut = Payload::from(json.clone());
195
196 assert_eq!(Payload::Text(vec![json.clone()], None), sut);
197
198 let sut = Payload::from(json.to_string());
200
201 assert_eq!(Payload::Text(vec![json], None), sut);
202 }
203
204 #[test]
205 fn test_from_binary() {
206 let sut = Payload::from(vec![1, 2, 3]);
207 assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3]), None), sut);
208
209 let sut = Payload::from(&[1_u8, 2_u8, 3_u8][..]);
210 assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3]), None), sut);
211
212 let sut = Payload::from(Bytes::from_static(&[1, 2, 3]));
213 assert_eq!(Payload::Binary(Bytes::from_static(&[1, 2, 3]), None), sut);
214 }
215
216 #[test]
217 fn test_payload_with_ack_id() {
218 let payload = Payload::from("test");
219 let payload_with_ack = Payload::with_ack_id(payload, 123);
220
221 assert_eq!(payload_with_ack.ack_id(), Some(123));
222
223 match payload_with_ack {
224 Payload::Text(data, Some(ack_id)) => {
225 assert_eq!(data, vec![serde_json::Value::String("test".to_string())]);
226 assert_eq!(ack_id, 123);
227 }
228 _ => panic!("Expected Text payload with ack_id"),
229 }
230 }
231
232 #[test]
233 fn test_payload_set_ack_id() {
234 let mut payload = Payload::from(vec![1, 2, 3]);
235 assert_eq!(payload.ack_id(), None);
236
237 payload.set_ack_id(Some(456));
238 assert_eq!(payload.ack_id(), Some(456));
239
240 payload.set_ack_id(None);
241 assert_eq!(payload.ack_id(), None);
242 }
243
244 #[test]
245 fn test_payload_data() {
246 let payload = Payload::with_ack_id(json!("test"), 789);
247
248 match payload.data() {
249 PayloadData::Text(data) => {
250 assert_eq!(data, &vec![json!("test")]);
251 }
252 _ => panic!("Expected Text data"),
253 }
254
255 assert_eq!(payload.ack_id(), Some(789));
257 }
258}