1use crate::types::*;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
8pub enum AMQPValue {
9 Boolean(Boolean),
11 ShortShortInt(ShortShortInt),
13 ShortShortUInt(ShortShortUInt),
15 ShortInt(ShortInt),
17 ShortUInt(ShortUInt),
19 LongInt(LongInt),
21 LongUInt(LongUInt),
23 LongLongInt(LongLongInt),
25 Float(Float),
27 Double(Double),
29 DecimalValue(DecimalValue),
31 ShortString(ShortString),
33 LongString(LongString),
35 FieldArray(FieldArray),
37 Timestamp(Timestamp),
39 FieldTable(FieldTable),
41 ByteArray(ByteArray),
43 Void,
45}
46
47impl AMQPValue {
48 pub fn get_type(&self) -> AMQPType {
50 match *self {
51 AMQPValue::Boolean(_) => AMQPType::Boolean,
52 AMQPValue::ShortShortInt(_) => AMQPType::ShortShortInt,
53 AMQPValue::ShortShortUInt(_) => AMQPType::ShortShortUInt,
54 AMQPValue::ShortInt(_) => AMQPType::ShortInt,
55 AMQPValue::ShortUInt(_) => AMQPType::ShortUInt,
56 AMQPValue::LongInt(_) => AMQPType::LongInt,
57 AMQPValue::LongUInt(_) => AMQPType::LongUInt,
58 AMQPValue::LongLongInt(_) => AMQPType::LongLongInt,
59 AMQPValue::Float(_) => AMQPType::Float,
60 AMQPValue::Double(_) => AMQPType::Double,
61 AMQPValue::DecimalValue(_) => AMQPType::DecimalValue,
62 AMQPValue::ShortString(_) => AMQPType::ShortString,
63 AMQPValue::LongString(_) => AMQPType::LongString,
64 AMQPValue::FieldArray(_) => AMQPType::FieldArray,
65 AMQPValue::Timestamp(_) => AMQPType::Timestamp,
66 AMQPValue::FieldTable(_) => AMQPType::FieldTable,
67 AMQPValue::ByteArray(_) => AMQPType::ByteArray,
68 AMQPValue::Void => AMQPType::Void,
69 }
70 }
71
72 pub fn try_from(value: &Value, amqp_type: AMQPType) -> Option<AMQPValue> {
74 match amqp_type {
75 AMQPType::Boolean => value.as_bool().map(AMQPValue::Boolean),
76 AMQPType::ShortShortInt => value
77 .as_i64()
78 .and_then(|i| ShortShortInt::try_from(i).ok())
79 .map(AMQPValue::ShortShortInt),
80 AMQPType::ShortShortUInt => value
81 .as_u64()
82 .and_then(|u| ShortShortUInt::try_from(u).ok())
83 .map(AMQPValue::ShortShortUInt),
84 AMQPType::ShortInt => value
85 .as_i64()
86 .and_then(|i| ShortInt::try_from(i).ok())
87 .map(AMQPValue::ShortInt),
88 AMQPType::ShortUInt => value
89 .as_u64()
90 .and_then(|u| ShortUInt::try_from(u).ok())
91 .map(AMQPValue::ShortUInt),
92 AMQPType::LongInt => value
93 .as_i64()
94 .and_then(|i| LongInt::try_from(i).ok())
95 .map(AMQPValue::LongInt),
96 AMQPType::LongUInt => value
97 .as_u64()
98 .and_then(|u| LongUInt::try_from(u).ok())
99 .map(AMQPValue::LongUInt),
100 AMQPType::LongLongInt => value
101 .as_i64()
102 .map(|i| AMQPValue::LongLongInt(i as LongLongInt)),
103 AMQPType::LongLongUInt => value
104 .as_u64()
105 .map(|u| AMQPValue::LongLongInt(u as LongLongInt)), AMQPType::Float => value.as_f64().map(|i| AMQPValue::Float(i as Float)),
107 AMQPType::Double => value.as_f64().map(|i| AMQPValue::Double(i as Double)),
108 AMQPType::DecimalValue => None,
109 AMQPType::ShortString => value
110 .as_str()
111 .map(ShortString::from)
112 .map(AMQPValue::ShortString),
113 AMQPType::LongString => value
114 .as_str()
115 .map(LongString::from)
116 .map(AMQPValue::LongString),
117 AMQPType::FieldArray => None,
118 AMQPType::Timestamp => value.as_u64().map(|t| AMQPValue::Timestamp(t as Timestamp)),
119 AMQPType::FieldTable => None,
120 AMQPType::ByteArray => None,
121 AMQPType::Void => value.as_null().map(|_| AMQPValue::Void),
122 }
123 }
124
125 pub fn as_void(&self) -> Option<()> {
127 matches!(self, AMQPValue::Void).then_some(())
128 }
129}
130
131macro_rules! amqp_value_getter {
132 ($(#[$meta:meta])* copy $method:ident, $variant:ident, $ty:ty) => {
133 $(#[$meta])*
134 pub fn $method(&self) -> Option<$ty> {
135 match self {
136 AMQPValue::$variant(value) => Some(*value),
137 _ => None,
138 }
139 }
140 };
141 ($(#[$meta:meta])* ref $method:ident, $variant:ident, $ty:ty) => {
142 $(#[$meta])*
143 pub fn $method(&self) -> Option<&$ty> {
144 match self {
145 AMQPValue::$variant(value) => Some(value),
146 _ => None,
147 }
148 }
149 };
150}
151
152impl AMQPValue {
153 amqp_value_getter!(
154 copy as_bool, Boolean, Boolean
156 );
157 amqp_value_getter!(
158 copy as_short_short_int, ShortShortInt, ShortShortInt
160 );
161 amqp_value_getter!(
162 copy as_short_short_uint, ShortShortUInt, ShortShortUInt
164 );
165 amqp_value_getter!(
166 copy as_short_int, ShortInt, ShortInt
168 );
169 amqp_value_getter!(
170 copy as_short_uint, ShortUInt, ShortUInt
172 );
173 amqp_value_getter!(
174 copy as_long_int, LongInt, LongInt
176 );
177 amqp_value_getter!(
178 copy as_long_uint, LongUInt, LongUInt
180 );
181 amqp_value_getter!(
182 copy as_long_long_int, LongLongInt, LongLongInt
184 );
185 amqp_value_getter!(
186 copy as_float, Float, Float
188 );
189 amqp_value_getter!(
190 copy as_double, Double, Double
192 );
193 amqp_value_getter!(
194 copy as_decimal_value, DecimalValue, DecimalValue
196 );
197 amqp_value_getter!(
198 copy as_timestamp, Timestamp, Timestamp
200 );
201 amqp_value_getter!(
202 ref as_short_string, ShortString, ShortString
204 );
205 amqp_value_getter!(
206 ref as_long_string, LongString, LongString
208 );
209 amqp_value_getter!(
210 ref as_array, FieldArray, FieldArray
212 );
213 amqp_value_getter!(
214 ref as_field_table, FieldTable, FieldTable
216 );
217 amqp_value_getter!(
218 ref as_byte_array, ByteArray, ByteArray
220 );
221}
222
223impl From<Boolean> for AMQPValue {
224 fn from(v: Boolean) -> Self {
225 AMQPValue::Boolean(v)
226 }
227}
228
229impl From<ShortShortInt> for AMQPValue {
230 fn from(v: ShortShortInt) -> Self {
231 AMQPValue::ShortShortInt(v)
232 }
233}
234
235impl From<ShortShortUInt> for AMQPValue {
236 fn from(v: ShortShortUInt) -> Self {
237 AMQPValue::ShortShortUInt(v)
238 }
239}
240
241impl From<ShortInt> for AMQPValue {
242 fn from(v: ShortInt) -> Self {
243 AMQPValue::ShortInt(v)
244 }
245}
246
247impl From<ShortUInt> for AMQPValue {
248 fn from(v: ShortUInt) -> Self {
249 AMQPValue::ShortUInt(v)
250 }
251}
252
253impl From<LongInt> for AMQPValue {
254 fn from(v: LongInt) -> Self {
255 AMQPValue::LongInt(v)
256 }
257}
258
259impl From<LongUInt> for AMQPValue {
260 fn from(v: LongUInt) -> Self {
261 AMQPValue::LongUInt(v)
262 }
263}
264
265impl From<LongLongInt> for AMQPValue {
266 fn from(v: LongLongInt) -> Self {
267 AMQPValue::LongLongInt(v)
268 }
269}
270
271impl From<Float> for AMQPValue {
272 fn from(v: Float) -> Self {
273 AMQPValue::Float(v)
274 }
275}
276
277impl From<Double> for AMQPValue {
278 fn from(v: Double) -> Self {
279 AMQPValue::Double(v)
280 }
281}
282
283impl From<DecimalValue> for AMQPValue {
284 fn from(v: DecimalValue) -> Self {
285 AMQPValue::DecimalValue(v)
286 }
287}
288
289impl From<ShortString> for AMQPValue {
290 fn from(v: ShortString) -> Self {
291 AMQPValue::ShortString(v)
292 }
293}
294
295impl From<LongString> for AMQPValue {
296 fn from(v: LongString) -> Self {
297 AMQPValue::LongString(v)
298 }
299}
300
301impl From<FieldArray> for AMQPValue {
302 fn from(v: FieldArray) -> Self {
303 AMQPValue::FieldArray(v)
304 }
305}
306
307impl From<Timestamp> for AMQPValue {
308 fn from(v: Timestamp) -> Self {
309 AMQPValue::Timestamp(v)
310 }
311}
312
313impl From<FieldTable> for AMQPValue {
314 fn from(v: FieldTable) -> Self {
315 AMQPValue::FieldTable(v)
316 }
317}
318
319impl From<ByteArray> for AMQPValue {
320 fn from(v: ByteArray) -> Self {
321 AMQPValue::ByteArray(v)
322 }
323}
324
325#[cfg(test)]
326mod test {
327 use super::*;
328
329 use serde_json::Number;
330
331 #[test]
332 fn test_from_bool_value() {
333 assert_eq!(
334 AMQPValue::try_from(&Value::Bool(false), AMQPType::Boolean),
335 Some(AMQPValue::Boolean(false))
336 );
337 assert_eq!(
338 AMQPValue::try_from(&Value::Bool(true), AMQPType::Boolean),
339 Some(AMQPValue::Boolean(true))
340 );
341 }
342
343 #[test]
344 fn test_from_number_value() {
345 assert_eq!(
346 AMQPValue::try_from(&Value::Number(Number::from(42)), AMQPType::LongLongUInt),
347 Some(AMQPValue::LongLongInt(42))
348 );
349 assert_eq!(
350 AMQPValue::try_from(&Value::Number(Number::from(-42)), AMQPType::LongLongInt),
351 Some(AMQPValue::LongLongInt(-42))
352 );
353 assert_eq!(
354 AMQPValue::try_from(
355 &Value::Number(Number::from_f64(42.42).unwrap()),
356 AMQPType::Double
357 ),
358 Some(AMQPValue::Double(42.42))
359 );
360 }
361
362 #[test]
363 fn test_from_string_value() {
364 assert_eq!(
365 AMQPValue::try_from(&Value::String(String::new()), AMQPType::LongString),
366 Some(AMQPValue::LongString(LongString::default()))
367 );
368 assert_eq!(
369 AMQPValue::try_from(&Value::String("test".to_string()), AMQPType::LongString),
370 Some(AMQPValue::LongString("test".into()))
371 );
372 }
373
374 #[test]
375 fn test_from_null_value() {
376 assert_eq!(
377 AMQPValue::try_from(&Value::Null, AMQPType::Void),
378 Some(AMQPValue::Void)
379 );
380 }
381}