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