amqp_codec/types/
variant.rs

1use std::hash::{Hash, Hasher};
2
3use bytes::Bytes;
4use bytestring::ByteString;
5use chrono::{DateTime, Utc};
6use fxhash::FxHashMap;
7use ordered_float::OrderedFloat;
8use uuid::Uuid;
9
10use crate::protocol::Annotations;
11use crate::types::{Descriptor, List, StaticSymbol, Str, Symbol};
12
13/// Represents an AMQP type for use in polymorphic collections
14#[derive(Debug, Eq, PartialEq, Hash, Clone, Display, From)]
15pub enum Variant {
16    /// Indicates an empty value.
17    Null,
18
19    /// Represents a true or false value.
20    Boolean(bool),
21
22    /// Integer in the range 0 to 2^8 - 1 inclusive.
23    Ubyte(u8),
24
25    /// Integer in the range 0 to 2^16 - 1 inclusive.
26    Ushort(u16),
27
28    /// Integer in the range 0 to 2^32 - 1 inclusive.
29    Uint(u32),
30
31    /// Integer in the range 0 to 2^64 - 1 inclusive.
32    Ulong(u64),
33
34    /// Integer in the range 0 to 2^7 - 1 inclusive.
35    Byte(i8),
36
37    /// Integer in the range 0 to 2^15 - 1 inclusive.
38    Short(i16),
39
40    /// Integer in the range 0 to 2^32 - 1 inclusive.
41    Int(i32),
42
43    /// Integer in the range 0 to 2^64 - 1 inclusive.
44    Long(i64),
45
46    /// 32-bit floating point number (IEEE 754-2008 binary32).
47    Float(OrderedFloat<f32>),
48
49    /// 64-bit floating point number (IEEE 754-2008 binary64).
50    Double(OrderedFloat<f64>),
51
52    // Decimal32(d32),
53    // Decimal64(d64),
54    // Decimal128(d128),
55    /// A single Unicode character.
56    Char(char),
57
58    /// An absolute point in time.
59    /// Represents an approximate point in time using the Unix time encoding of
60    /// UTC with a precision of milliseconds. For example, 1311704463521
61    /// represents the moment 2011-07-26T18:21:03.521Z.
62    Timestamp(DateTime<Utc>),
63
64    /// A universally unique identifier as defined by RFC-4122 section 4.1.2
65    Uuid(Uuid),
66
67    /// A sequence of octets.
68    #[display(fmt = "Binary({:?})", _0)]
69    Binary(Bytes),
70
71    /// A sequence of Unicode characters
72    String(Str),
73
74    /// Symbolic values from a constrained domain.
75    Symbol(Symbol),
76
77    /// Same as Symbol but for static refs
78    StaticSymbol(StaticSymbol),
79
80    /// List
81    #[display(fmt = "List({:?})", _0)]
82    List(List),
83
84    /// Map
85    Map(VariantMap),
86
87    /// Described value
88    #[display(fmt = "Described{:?}", _0)]
89    Described((Descriptor, Box<Variant>)),
90}
91
92impl From<ByteString> for Variant {
93    fn from(s: ByteString) -> Self {
94        Str::from(s).into()
95    }
96}
97
98impl From<String> for Variant {
99    fn from(s: String) -> Self {
100        Str::from(ByteString::from(s)).into()
101    }
102}
103
104impl From<&'static str> for Variant {
105    fn from(s: &'static str) -> Self {
106        Str::from(s).into()
107    }
108}
109
110impl PartialEq<str> for Variant {
111    fn eq(&self, other: &str) -> bool {
112        match self {
113            Variant::String(s) => s == other,
114            Variant::Symbol(s) => s == other,
115            _ => false,
116        }
117    }
118}
119
120impl Variant {
121    pub fn as_str(&self) -> Option<&str> {
122        match self {
123            Variant::String(s) => Some(s.as_str()),
124            Variant::Symbol(s) => Some(s.as_str()),
125            _ => None,
126        }
127    }
128
129    pub fn as_int(&self) -> Option<i32> {
130        match self {
131            Variant::Int(v) => Some(*v as i32),
132            _ => None,
133        }
134    }
135
136    pub fn as_long(&self) -> Option<i64> {
137        match self {
138            Variant::Ubyte(v) => Some(*v as i64),
139            Variant::Ushort(v) => Some(*v as i64),
140            Variant::Uint(v) => Some(*v as i64),
141            Variant::Ulong(v) => Some(*v as i64),
142            Variant::Byte(v) => Some(*v as i64),
143            Variant::Short(v) => Some(*v as i64),
144            Variant::Int(v) => Some(*v as i64),
145            Variant::Long(v) => Some(*v as i64),
146            _ => None,
147        }
148    }
149
150    pub fn to_bytes_str(&self) -> Option<ByteString> {
151        match self {
152            Variant::String(s) => Some(s.to_bytes_str()),
153            Variant::Symbol(s) => Some(s.to_bytes_str()),
154            _ => None,
155        }
156    }
157}
158
159#[derive(PartialEq, Eq, Clone, Debug, Display)]
160#[display(fmt = "{:?}", map)]
161pub struct VariantMap {
162    pub map: FxHashMap<Variant, Variant>,
163}
164
165impl VariantMap {
166    pub fn new(map: FxHashMap<Variant, Variant>) -> VariantMap {
167        VariantMap { map }
168    }
169}
170
171impl Hash for VariantMap {
172    fn hash<H: Hasher>(&self, _state: &mut H) {
173        unimplemented!()
174    }
175}
176
177#[derive(PartialEq, Clone, Debug, Display)]
178#[display(fmt = "{:?}", _0)]
179pub struct VecSymbolMap(pub Vec<(Symbol, Variant)>);
180
181impl Default for VecSymbolMap {
182    fn default() -> Self {
183        VecSymbolMap(Vec::with_capacity(8))
184    }
185}
186
187impl From<Annotations> for VecSymbolMap {
188    fn from(anns: Annotations) -> VecSymbolMap {
189        VecSymbolMap(anns.into_iter().collect())
190    }
191}
192
193impl std::ops::Deref for VecSymbolMap {
194    type Target = Vec<(Symbol, Variant)>;
195
196    fn deref(&self) -> &Self::Target {
197        &self.0
198    }
199}
200
201impl std::ops::DerefMut for VecSymbolMap {
202    fn deref_mut(&mut self) -> &mut Self::Target {
203        &mut self.0
204    }
205}
206
207#[derive(PartialEq, Clone, Debug, Display)]
208#[display(fmt = "{:?}", _0)]
209pub struct VecStringMap(pub Vec<(Str, Variant)>);
210
211impl Default for VecStringMap {
212    fn default() -> Self {
213        VecStringMap(Vec::with_capacity(8))
214    }
215}
216
217impl From<FxHashMap<Str, Variant>> for VecStringMap {
218    fn from(map: FxHashMap<Str, Variant>) -> VecStringMap {
219        VecStringMap(map.into_iter().collect())
220    }
221}
222
223impl std::ops::Deref for VecStringMap {
224    type Target = Vec<(Str, Variant)>;
225
226    fn deref(&self) -> &Self::Target {
227        &self.0
228    }
229}
230
231impl std::ops::DerefMut for VecStringMap {
232    fn deref_mut(&mut self) -> &mut Self::Target {
233        &mut self.0
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    fn bytes_eq() {
243        let bytes1 = Variant::Binary(Bytes::from(&b"hello"[..]));
244        let bytes2 = Variant::Binary(Bytes::from(&b"hello"[..]));
245        let bytes3 = Variant::Binary(Bytes::from(&b"world"[..]));
246
247        assert_eq!(bytes1, bytes2);
248        assert!(bytes1 != bytes3);
249    }
250
251    #[test]
252    fn string_eq() {
253        let a = Variant::String(ByteString::from("hello").into());
254        let b = Variant::String(ByteString::from("world!").into());
255
256        assert_eq!(Variant::String(ByteString::from("hello").into()), a);
257        assert!(a != b);
258    }
259
260    #[test]
261    fn symbol_eq() {
262        let a = Variant::Symbol(Symbol::from("hello"));
263        let b = Variant::Symbol(Symbol::from("world!"));
264
265        assert_eq!(Variant::Symbol(Symbol::from("hello")), a);
266        assert!(a != b);
267    }
268}