Skip to main content

amq_protocol_types/
value.rs

1use crate::types::*;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// Enumeration referencing the possible AMQP values depending on the types
7#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
8pub enum AMQPValue {
9    /// A bool
10    Boolean(Boolean),
11    /// An i8
12    ShortShortInt(ShortShortInt),
13    /// A u8
14    ShortShortUInt(ShortShortUInt),
15    /// An i16
16    ShortInt(ShortInt),
17    /// A u16
18    ShortUInt(ShortUInt),
19    /// An i32
20    LongInt(LongInt),
21    /// A u32
22    LongUInt(LongUInt),
23    /// An i64
24    LongLongInt(LongLongInt),
25    /// An f32
26    Float(Float),
27    /// An f64
28    Double(Double),
29    /// A decimal value
30    DecimalValue(DecimalValue),
31    /// A String (deprecated)
32    ShortString(ShortString),
33    /// A String
34    LongString(LongString),
35    /// An array of AMQPValue
36    FieldArray(FieldArray),
37    /// A timestamp (u64)
38    Timestamp(Timestamp),
39    /// A Map<String, AMQPValue>
40    FieldTable(FieldTable),
41    /// An array of bytes (RabbitMQ specific)
42    ByteArray(ByteArray),
43    /// No value
44    Void,
45}
46
47impl AMQPValue {
48    /// Get the AMQPType of an AMQPValue
49    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    /// Convert a serde_json::Value into an AMQPValue
73    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)), /* Not a typo; AMQPValue::LongLongUInt doesn't exist; reinterpret bits as i64 */
106            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    /// If the value is bool, returns associated value. Returns None otherwise.
126    pub fn as_bool(&self) -> Option<Boolean> {
127        match self {
128            AMQPValue::Boolean(value) => Some(*value),
129            _ => None,
130        }
131    }
132
133    /// If the value is ShortShortInt, returns associated value. Returns None otherwise.
134    pub fn as_short_short_int(&self) -> Option<ShortShortInt> {
135        match self {
136            AMQPValue::ShortShortInt(value) => Some(*value),
137            _ => None,
138        }
139    }
140
141    /// If the value is ShortShortUInt, returns associated value. Returns None otherwise.
142    pub fn as_short_short_uint(&self) -> Option<ShortShortUInt> {
143        match self {
144            AMQPValue::ShortShortUInt(value) => Some(*value),
145            _ => None,
146        }
147    }
148
149    /// If the value is ShortInt, returns associated value. Returns None otherwise.
150    pub fn as_short_int(&self) -> Option<ShortInt> {
151        match self {
152            AMQPValue::ShortInt(value) => Some(*value),
153            _ => None,
154        }
155    }
156
157    /// If the value is ShortUInt, returns associated value. Returns None otherwise.
158    pub fn as_short_uint(&self) -> Option<ShortUInt> {
159        match self {
160            AMQPValue::ShortUInt(value) => Some(*value),
161            _ => None,
162        }
163    }
164
165    /// If the value is LongInt, returns associated value. Returns None otherwise.
166    pub fn as_long_int(&self) -> Option<LongInt> {
167        match self {
168            AMQPValue::LongInt(value) => Some(*value),
169            _ => None,
170        }
171    }
172
173    /// If the value is LongUInt, returns associated value. Returns None otherwise.
174    pub fn as_long_uint(&self) -> Option<LongUInt> {
175        match self {
176            AMQPValue::LongUInt(value) => Some(*value),
177            _ => None,
178        }
179    }
180
181    /// If the value is LongLongInt, returns associated value. Returns None otherwise.
182    pub fn as_long_long_int(&self) -> Option<LongLongInt> {
183        match self {
184            AMQPValue::LongLongInt(value) => Some(*value),
185            _ => None,
186        }
187    }
188
189    /// If the value is Float, returns associated value. Returns None otherwise.
190    pub fn as_float(&self) -> Option<Float> {
191        match self {
192            AMQPValue::Float(value) => Some(*value),
193            _ => None,
194        }
195    }
196
197    /// If the value is Double, returns associated value. Returns None otherwise.
198    pub fn as_double(&self) -> Option<Double> {
199        match self {
200            AMQPValue::Double(value) => Some(*value),
201            _ => None,
202        }
203    }
204
205    /// If the value is DecimalValue, returns associated value. Returns None otherwise.
206    pub fn as_decimal_value(&self) -> Option<DecimalValue> {
207        match self {
208            AMQPValue::DecimalValue(value) => Some(*value),
209            _ => None,
210        }
211    }
212
213    /// If the value is ShortString, returns associated value as str. Returns None otherwise.
214    pub fn as_short_string(&self) -> Option<&ShortString> {
215        match self {
216            AMQPValue::ShortString(value) => Some(value),
217            _ => None,
218        }
219    }
220
221    /// If the value is LongString, returns associated value as bytes. Returns None otherwise.
222    pub fn as_long_string(&self) -> Option<&LongString> {
223        match self {
224            AMQPValue::LongString(value) => Some(value),
225            _ => None,
226        }
227    }
228
229    /// If the value is FieldArray, returns associated value. Returns None otherwise.
230    pub fn as_array(&self) -> Option<&FieldArray> {
231        match self {
232            AMQPValue::FieldArray(value) => Some(value),
233            _ => None,
234        }
235    }
236
237    /// If the value is Timestamp, returns associated value. Returns None otherwise.
238    pub fn as_timestamp(&self) -> Option<Timestamp> {
239        match self {
240            AMQPValue::Timestamp(value) => Some(*value),
241            _ => None,
242        }
243    }
244
245    /// If the value is FieldTable, returns associated value. Returns None otherwise.
246    pub fn as_field_table(&self) -> Option<&FieldTable> {
247        match self {
248            AMQPValue::FieldTable(value) => Some(value),
249            _ => None,
250        }
251    }
252
253    /// If the value is ByteArray, returns associated value. Returns None otherwise.
254    pub fn as_byte_array(&self) -> Option<&ByteArray> {
255        match self {
256            AMQPValue::ByteArray(value) => Some(value),
257            _ => None,
258        }
259    }
260
261    /// Returns true if value is Void.
262    pub fn as_void(&self) -> Option<()> {
263        match self {
264            AMQPValue::Void => Some(()),
265            _ => None,
266        }
267    }
268}
269
270impl From<Boolean> for AMQPValue {
271    fn from(v: Boolean) -> Self {
272        AMQPValue::Boolean(v)
273    }
274}
275
276impl From<ShortShortInt> for AMQPValue {
277    fn from(v: ShortShortInt) -> Self {
278        AMQPValue::ShortShortInt(v)
279    }
280}
281
282impl From<ShortShortUInt> for AMQPValue {
283    fn from(v: ShortShortUInt) -> Self {
284        AMQPValue::ShortShortUInt(v)
285    }
286}
287
288impl From<ShortInt> for AMQPValue {
289    fn from(v: ShortInt) -> Self {
290        AMQPValue::ShortInt(v)
291    }
292}
293
294impl From<ShortUInt> for AMQPValue {
295    fn from(v: ShortUInt) -> Self {
296        AMQPValue::ShortUInt(v)
297    }
298}
299
300impl From<LongInt> for AMQPValue {
301    fn from(v: LongInt) -> Self {
302        AMQPValue::LongInt(v)
303    }
304}
305
306impl From<LongUInt> for AMQPValue {
307    fn from(v: LongUInt) -> Self {
308        AMQPValue::LongUInt(v)
309    }
310}
311
312impl From<LongLongInt> for AMQPValue {
313    fn from(v: LongLongInt) -> Self {
314        AMQPValue::LongLongInt(v)
315    }
316}
317
318impl From<Float> for AMQPValue {
319    fn from(v: Float) -> Self {
320        AMQPValue::Float(v)
321    }
322}
323
324impl From<Double> for AMQPValue {
325    fn from(v: Double) -> Self {
326        AMQPValue::Double(v)
327    }
328}
329
330impl From<DecimalValue> for AMQPValue {
331    fn from(v: DecimalValue) -> Self {
332        AMQPValue::DecimalValue(v)
333    }
334}
335
336impl From<ShortString> for AMQPValue {
337    fn from(v: ShortString) -> Self {
338        AMQPValue::ShortString(v)
339    }
340}
341
342impl From<LongString> for AMQPValue {
343    fn from(v: LongString) -> Self {
344        AMQPValue::LongString(v)
345    }
346}
347
348impl From<FieldArray> for AMQPValue {
349    fn from(v: FieldArray) -> Self {
350        AMQPValue::FieldArray(v)
351    }
352}
353
354impl From<Timestamp> for AMQPValue {
355    fn from(v: Timestamp) -> Self {
356        AMQPValue::Timestamp(v)
357    }
358}
359
360impl From<FieldTable> for AMQPValue {
361    fn from(v: FieldTable) -> Self {
362        AMQPValue::FieldTable(v)
363    }
364}
365
366impl From<ByteArray> for AMQPValue {
367    fn from(v: ByteArray) -> Self {
368        AMQPValue::ByteArray(v)
369    }
370}
371
372#[cfg(test)]
373mod test {
374    use super::*;
375
376    use serde_json::Number;
377
378    #[test]
379    fn test_from_bool_value() {
380        assert_eq!(
381            AMQPValue::try_from(&Value::Bool(false), AMQPType::Boolean),
382            Some(AMQPValue::Boolean(false))
383        );
384        assert_eq!(
385            AMQPValue::try_from(&Value::Bool(true), AMQPType::Boolean),
386            Some(AMQPValue::Boolean(true))
387        );
388    }
389
390    #[test]
391    fn test_from_number_value() {
392        assert_eq!(
393            AMQPValue::try_from(&Value::Number(Number::from(42)), AMQPType::LongLongUInt),
394            Some(AMQPValue::LongLongInt(42))
395        );
396        assert_eq!(
397            AMQPValue::try_from(&Value::Number(Number::from(-42)), AMQPType::LongLongInt),
398            Some(AMQPValue::LongLongInt(-42))
399        );
400        assert_eq!(
401            AMQPValue::try_from(
402                &Value::Number(Number::from_f64(42.42).unwrap()),
403                AMQPType::Double
404            ),
405            Some(AMQPValue::Double(42.42))
406        );
407    }
408
409    #[test]
410    fn test_from_string_value() {
411        assert_eq!(
412            AMQPValue::try_from(&Value::String(String::new()), AMQPType::LongString),
413            Some(AMQPValue::LongString(LongString::default()))
414        );
415        assert_eq!(
416            AMQPValue::try_from(&Value::String("test".to_string()), AMQPType::LongString),
417            Some(AMQPValue::LongString("test".into()))
418        );
419    }
420
421    #[test]
422    fn test_from_null_value() {
423        assert_eq!(
424            AMQPValue::try_from(&Value::Null, AMQPType::Void),
425            Some(AMQPValue::Void)
426        );
427    }
428}