1use std::hash::{Hash, Hasher};
2
3use chrono::{DateTime, Utc};
4use ntex_bytes::{ByteString, Bytes, BytesMut};
5use ordered_float::OrderedFloat;
6use uuid::Uuid;
7
8use crate::types::{Array, Descriptor, List, Str, Symbol};
9use crate::{AmqpParseError, Decode, Encode, HashMap, protocol::Annotations};
10
11#[derive(Debug, Eq, PartialEq, Hash, Clone, From)]
13pub enum Variant {
14 Null,
16
17 Boolean(bool),
19
20 Ubyte(u8),
22
23 Ushort(u16),
25
26 Uint(u32),
28
29 Ulong(u64),
31
32 Byte(i8),
34
35 Short(i16),
37
38 Int(i32),
40
41 Long(i64),
43
44 Float(OrderedFloat<f32>),
46
47 Double(OrderedFloat<f64>),
49
50 Decimal32([u8; 4]),
52
53 Decimal64([u8; 8]),
55
56 Decimal128([u8; 16]),
58
59 Char(char),
61
62 Timestamp(DateTime<Utc>),
67
68 Uuid(Uuid),
70
71 Binary(Bytes),
73
74 String(Str),
76
77 Symbol(Symbol),
79
80 List(List),
82
83 Map(VariantMap),
85
86 Array(Array),
88
89 Described((Descriptor, Box<Variant>)),
91
92 DescribedCompound(DescribedCompound),
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Hash)]
99pub struct DescribedCompound {
100 descriptor: Descriptor,
101 pub(crate) data: Bytes,
102}
103
104impl DescribedCompound {
105 pub fn create<T: Encode>(descriptor: Descriptor, value: T) -> Self {
116 let size = value.encoded_size();
117 let mut buf = BytesMut::with_capacity(size);
118 value.encode(&mut buf);
119 DescribedCompound {
120 descriptor,
121 data: buf.freeze(),
122 }
123 }
124
125 pub(crate) fn new(descriptor: Descriptor, data: Bytes) -> Self {
126 DescribedCompound { descriptor, data }
127 }
128
129 pub fn descriptor(&self) -> &Descriptor {
130 &self.descriptor
131 }
132
133 pub fn decode<T: Decode>(&self) -> Result<T, AmqpParseError> {
144 let mut buf = self.data.clone();
145 let result = T::decode(&mut buf)?;
146 if buf.is_empty() {
147 Ok(result)
148 } else {
149 Err(AmqpParseError::InvalidSize)
150 }
151 }
152}
153
154impl Encode for DescribedCompound {
155 fn encoded_size(&self) -> usize {
156 self.descriptor.encoded_size() + self.data.len()
157 }
158
159 fn encode(&self, buf: &mut BytesMut) {
160 self.descriptor.encode(buf);
161 buf.extend_from_slice(&self.data);
162 }
163}
164
165impl From<HashMap<Variant, Variant>> for Variant {
166 fn from(data: HashMap<Variant, Variant>) -> Self {
167 Variant::Map(VariantMap { map: data })
168 }
169}
170
171impl From<ByteString> for Variant {
172 fn from(s: ByteString) -> Self {
173 Str::from(s).into()
174 }
175}
176
177impl From<String> for Variant {
178 fn from(s: String) -> Self {
179 Str::from(ByteString::from(s)).into()
180 }
181}
182
183impl From<&'static str> for Variant {
184 fn from(s: &'static str) -> Self {
185 Str::from(s).into()
186 }
187}
188
189impl PartialEq<str> for Variant {
190 fn eq(&self, other: &str) -> bool {
191 match self {
192 Variant::String(s) => s == other,
193 Variant::Symbol(s) => s == other,
194 _ => false,
195 }
196 }
197}
198
199impl Variant {
200 pub fn as_str(&self) -> Option<&str> {
201 match self {
202 Variant::String(s) => Some(s.as_str()),
203 Variant::Symbol(s) => Some(s.as_str()),
204 _ => None,
205 }
206 }
207
208 pub fn as_long(&self) -> Option<i64> {
211 match self {
212 Variant::Ubyte(v) => Some(*v as i64),
213 Variant::Ushort(v) => Some(*v as i64),
214 Variant::Uint(v) => Some(*v as i64),
215 Variant::Byte(v) => Some(*v as i64),
216 Variant::Short(v) => Some(*v as i64),
217 Variant::Int(v) => Some(*v as i64),
218 Variant::Long(v) => Some(*v),
219 _ => None,
220 }
221 }
222
223 pub fn as_ulong(&self) -> Option<u64> {
225 match self {
226 Variant::Ubyte(v) => Some(*v as u64),
227 Variant::Ushort(v) => Some(*v as u64),
228 Variant::Uint(v) => Some(*v as u64),
229 Variant::Ulong(v) => Some(*v),
230 _ => None,
231 }
232 }
233
234 pub fn to_bytes_str(&self) -> Option<ByteString> {
235 match self {
236 Variant::String(s) => Some(s.to_bytes_str()),
237 Variant::Symbol(s) => Some(s.to_bytes_str()),
238 _ => None,
239 }
240 }
241}
242
243#[derive(PartialEq, Eq, Clone, Debug)]
244pub struct VariantMap {
245 pub map: HashMap<Variant, Variant>,
246}
247
248impl VariantMap {
249 pub fn new(map: HashMap<Variant, Variant>) -> VariantMap {
250 VariantMap { map }
251 }
252}
253
254#[allow(clippy::derived_hash_with_manual_eq)]
255impl Hash for VariantMap {
256 fn hash<H: Hasher>(&self, _state: &mut H) {
257 unimplemented!()
258 }
259}
260
261#[derive(PartialEq, Eq, Clone, Debug)]
262pub struct VecSymbolMap(pub Vec<(Symbol, Variant)>);
263
264impl Default for VecSymbolMap {
265 fn default() -> Self {
266 VecSymbolMap(Vec::with_capacity(8))
267 }
268}
269
270impl From<Annotations> for VecSymbolMap {
271 fn from(anns: Annotations) -> VecSymbolMap {
272 VecSymbolMap(anns.into_iter().collect())
273 }
274}
275
276impl From<Vec<(Symbol, Variant)>> for VecSymbolMap {
277 fn from(data: Vec<(Symbol, Variant)>) -> VecSymbolMap {
278 VecSymbolMap(data)
279 }
280}
281
282impl std::ops::Deref for VecSymbolMap {
283 type Target = Vec<(Symbol, Variant)>;
284
285 fn deref(&self) -> &Self::Target {
286 &self.0
287 }
288}
289
290impl std::ops::DerefMut for VecSymbolMap {
291 fn deref_mut(&mut self) -> &mut Self::Target {
292 &mut self.0
293 }
294}
295
296#[derive(PartialEq, Eq, Clone, Debug)]
297pub struct VecStringMap(pub Vec<(Str, Variant)>);
298
299impl Default for VecStringMap {
300 fn default() -> Self {
301 VecStringMap(Vec::with_capacity(8))
302 }
303}
304
305impl From<Vec<(Str, Variant)>> for VecStringMap {
306 fn from(data: Vec<(Str, Variant)>) -> VecStringMap {
307 VecStringMap(data)
308 }
309}
310
311impl From<HashMap<Str, Variant>> for VecStringMap {
312 fn from(map: HashMap<Str, Variant>) -> VecStringMap {
313 VecStringMap(map.into_iter().collect())
314 }
315}
316
317impl std::ops::Deref for VecStringMap {
318 type Target = Vec<(Str, Variant)>;
319
320 fn deref(&self) -> &Self::Target {
321 &self.0
322 }
323}
324
325impl std::ops::DerefMut for VecStringMap {
326 fn deref_mut(&mut self) -> &mut Self::Target {
327 &mut self.0
328 }
329}
330
331#[cfg(test)]
332mod tests {
333 use ntex_bytes::{Buf, BufMut};
334
335 use crate::{codec::ListHeader, format_codes};
336
337 use super::*;
338
339 #[test]
340 fn bytes_eq() {
341 let bytes1 = Variant::Binary(Bytes::from(&b"hello"[..]));
342 let bytes2 = Variant::Binary(Bytes::from(&b"hello"[..]));
343 let bytes3 = Variant::Binary(Bytes::from(&b"world"[..]));
344
345 assert_eq!(bytes1, bytes2);
346 assert!(bytes1 != bytes3);
347 }
348
349 #[test]
350 fn string_eq() {
351 let a = Variant::String(ByteString::from("hello").into());
352 let b = Variant::String(ByteString::from("world!").into());
353
354 assert_eq!(Variant::String(ByteString::from("hello").into()), a);
355 assert!(a != b);
356 }
357
358 #[test]
359 fn symbol_eq() {
360 let a = Variant::Symbol(Symbol::from("hello"));
361 let b = Variant::Symbol(Symbol::from("world!"));
362
363 assert_eq!(Variant::Symbol(Symbol::from("hello")), a);
364 assert!(a != b);
365 }
366
367 #[derive(Debug, PartialEq, Eq, Clone)]
374 struct CustomList {
375 field1: ByteString,
376 field2: u8,
377 field3: Option<ByteString>,
378 }
379
380 impl CustomList {
381 fn encoded_data_size(&self) -> usize {
382 let mut size = self.field1.encoded_size() + self.field2.encoded_size();
383 if let Some(ref field3) = self.field3 {
384 size += field3.encoded_size();
385 }
386 size
387 }
388 }
389
390 impl crate::DecodeFormatted for CustomList {
391 fn decode_with_format(input: &mut Bytes, fmt: u8) -> Result<Self, AmqpParseError> {
392 let header = ListHeader::decode_with_format(input, fmt)?;
393 if header.count < 2 {
394 return Err(AmqpParseError::RequiredFieldOmitted("field2"));
395 }
396 let field1 = ByteString::decode(input)?;
397 let field2 = u8::decode(input)?;
398 let field3 = if header.count == 3 {
399 Some(ByteString::decode(input)?)
400 } else {
401 None
402 };
403 if input.has_remaining() {
404 return Err(AmqpParseError::InvalidSize);
405 }
406 Ok(CustomList {
407 field1,
408 field2,
409 field3,
410 })
411 }
412 }
413
414 impl crate::Encode for CustomList {
415 fn encoded_size(&self) -> usize {
416 let size = self.encoded_data_size();
417 if size + 1 > u8::MAX as usize {
418 size + 9 } else {
420 size + 3 }
422 }
423
424 fn encode(&self, buf: &mut BytesMut) {
425 let count = if self.field3.is_some() { 3u8 } else { 2u8 };
426 let data_size = self.encoded_data_size();
427 if data_size + 1 > u8::MAX as usize {
428 buf.put_u8(format_codes::FORMATCODE_LIST32);
429 buf.put_u32((4 + data_size) as u32); buf.put_u32(count as u32); } else {
432 buf.put_u8(format_codes::FORMATCODE_LIST8);
433 buf.put_u8((1 + data_size) as u8); buf.put_u8(count); }
436 self.field1.encode(buf);
437 self.field2.encode(buf);
438 if let Some(ref field3) = self.field3 {
439 field3.encode(buf);
440 }
441 }
442 }
443
444 #[test]
445 fn described_custom_list_recoding() {
446 let custom_list = CustomList {
447 field1: ByteString::from("value1"),
448 field2: 115,
449 field3: Some(ByteString::from("value3")),
450 };
451 let value = Variant::DescribedCompound(DescribedCompound::create(
452 Descriptor::Symbol("contoso:test".into()),
453 custom_list.clone(),
454 ));
455 let mut buf = BytesMut::with_capacity(value.encoded_size());
456 value.encode(&mut buf);
457 let data = buf.freeze();
458 assert_eq!(
459 data.as_ref(),
460 &b"\x00\xa3\x0ccontoso:test\xc0\x13\x03\xa1\x06value1\x50\x73\xa1\x06value3"[..]
461 );
462 let mut input = data.clone();
463 let decoded = Variant::decode(&mut input).unwrap();
464 assert_eq!(decoded, value);
465 let decoded_list = match decoded {
466 Variant::DescribedCompound(desc) => desc.decode::<CustomList>().unwrap(),
467 _ => panic!("Expected a described compound"),
468 };
469 assert_eq!(decoded_list, custom_list);
470 }
471}