x_variant/
variant.rs

1use std::{
2    collections::HashMap,
3    ops::{Index, IndexMut},
4    sync::{Arc, RwLock},
5};
6
7use num::traits::FromPrimitive;
8
9#[derive(Clone, Debug, PartialEq)]
10pub enum Variant {
11    None,
12    Bool(bool),
13    Int8(i8),
14    UInt8(u8),
15    Int16(i16),
16    UInt16(u16),
17    Int32(i32),
18    UInt32(u32),
19    Int64(i64),
20    UInt64(u64),
21    Float(f32),
22    Double(f64),
23    String(String),
24    Buffer(Vec<u8>),
25    Array(Vec<Variant>),
26    Dict(HashMap<String, Variant>),
27}
28
29macro_rules! variant_from_traits {
30    ($(($vtype:ident, $value_type:ty)),+) => {
31        $(
32            impl From<$value_type> for Variant {
33                fn from(value: $value_type) -> Self {
34                    Variant::$vtype(value)
35                }
36            }
37
38            impl From<Variant> for $value_type {
39                fn from(value: Variant) -> Self {
40                    match value {
41                        Variant::$vtype(v) => v,
42                        _ => Self::default(),
43                    }
44                }
45            }
46        )+
47    };
48}
49
50macro_rules! variant_number_from_traits {
51    ($(($vtype:ident, $value_type:ty)),+) => {
52        $(
53            impl From<$value_type> for Variant {
54                fn from(value: $value_type) -> Self {
55                    Variant::$vtype(value)
56                }
57            }
58
59            impl From<Variant> for $value_type {
60                fn from(value: Variant) -> Self {
61                    match value {
62                        Variant::$vtype(v) => v,
63                        _ => value.get_number::<Self>().unwrap_or_default(),
64                    }
65                }
66            }
67        )+
68    };
69}
70
71variant_from_traits! {
72    (Bool, bool),
73    (String, String),
74    (Buffer, Vec<u8>),
75    (Array, Vec<Variant>),
76    (Dict, HashMap<String, Variant>)
77}
78
79variant_number_from_traits! {
80    (Int8, i8),
81    (UInt8, u8),
82    (Int16, i16),
83    (UInt16, u16),
84    (Int32, i32),
85    (UInt32, u32),
86    (Int64, i64),
87    (UInt64, u64),
88    (Float, f32),
89    (Double, f64)
90}
91
92impl From<&str> for Variant {
93    fn from(value: &str) -> Self {
94        Variant::String(value.to_string())
95    }
96}
97
98macro_rules! variant_getters {
99    ($(($get:ident, $vtype:ident, $value_type:ty)),+) => {
100        $(
101            pub fn $get(&self) -> Option<$value_type> {
102                match self {
103                    Variant::$vtype(v) => Some(v.clone()),
104                    _ => None,
105                }
106            }
107        )+
108    };
109}
110
111macro_rules! variant_number_getters {
112    ($(($get:ident, $vtype:ident, $value_type:ty)),+) => {
113        $(
114            pub fn $get(&self) -> Option<$value_type> {
115                match self {
116                    Variant::$vtype(v) => Some(v.clone()),
117                    _ => self.get_number::<$value_type>(),
118                }
119            }
120        )+
121    };
122}
123
124macro_rules! variant_methods {
125    ($(($get:ident, $set:ident, $array_add:ident, $array_get:ident, $array_set:ident, $dict_set:ident, $dict_get:ident, $vtype:ident, $value_type:ty)),+) => {
126        $(
127            pub fn $set(&mut self, value: $value_type) {
128                *self = Variant::from(value);
129            }
130
131            pub fn $array_add(&mut self, value: $value_type) {
132                match self {
133                    Variant::Array(v) => {
134                        v.push(Variant::from(value));
135                    },
136                    _ => (),
137                }
138            }
139
140            pub fn $array_get(&self, index: usize) -> Option<$value_type> {
141                match self {
142                    Variant::Array(array) => {
143                        array.get(index)?.$get()
144                    },
145                    _ => None,
146                }
147            }
148
149            pub fn $array_set(&mut self, index: usize, value: $value_type) {
150                match self {
151                    Variant::Array(array) => {
152                        if index >= array.len() {
153                            array.resize(index + 1, Variant::None);
154                        }
155                        array[index] = Variant::from(value);
156                    },
157                    _ => (),
158                }
159            }
160
161            pub fn $dict_get(&self, key: &str) -> Option<$value_type> {
162                match self {
163                    Variant::Dict(dict) => {
164                        dict.get(key)?.$get()
165                    }
166                    _ => None,
167                }
168            }
169
170            pub fn $dict_set(&mut self, key: &str, value: $value_type) {
171                match self {
172                    Variant::Dict(v) => {
173                        v.insert(key.to_string(), Variant::from(value));
174                    },
175                    _ => (),
176                }
177            }
178        )+
179    };
180}
181
182impl Variant {
183    pub fn new() -> Self {
184        Variant::None
185    }
186
187    pub fn new_array() -> Self {
188        Variant::Array(Vec::new())
189    }
190
191    pub fn new_dict() -> Variant {
192        Variant::Dict(HashMap::new())
193    }
194
195    pub fn len(&self) -> usize {
196        match self {
197            Variant::String(v) => v.len(),
198            Variant::Buffer(v) => v.len(),
199            Variant::Array(v) => v.len(),
200            Variant::Dict(v) => v.len(),
201            _ => 0,
202        }
203    }
204
205    fn reset_value(&mut self) {
206        match self {
207            Variant::Bool(v) => *v = false,
208            Variant::Int8(v) => *v = 0,
209            Variant::UInt8(v) => *v = 0,
210            Variant::Int16(v) => *v = 0,
211            Variant::UInt16(v) => *v = 0,
212            Variant::Int32(v) => *v = 0,
213            Variant::UInt32(v) => *v = 0,
214            Variant::Int64(v) => *v = 0,
215            Variant::UInt64(v) => *v = 0,
216            Variant::Float(v) => *v = 0.0,
217            Variant::Double(v) => *v = 0.0,
218            Variant::String(v) => v.clear(),
219            Variant::Buffer(v) => v.clear(),
220            Variant::Array(v) => v.clear(),
221            Variant::Dict(v) => v.clear(),
222            _ => (),
223        }
224    }
225
226    pub fn clear(&mut self) {
227        match self {
228            Variant::String(v) => v.clear(),
229            Variant::Buffer(v) => v.clear(),
230            Variant::Array(v) => v.clear(),
231            Variant::Dict(v) => v.clear(),
232            _ => self.reset_value(),
233        }
234    }
235
236    pub fn concat(&mut self, other: &Self) -> bool {
237        match (self, other) {
238            (Variant::String(v1), Variant::String(v2)) => {
239                v1.push_str(v2);
240                true
241            }
242            (Variant::Buffer(v1), Variant::Buffer(v2)) => {
243                v1.append(&mut v2.clone());
244                true
245            }
246            (Variant::Array(v1), Variant::Array(v2)) => {
247                v1.append(&mut v2.clone());
248                true
249            }
250            (Variant::Dict(v1), Variant::Dict(v2)) => {
251                v1.extend(v2.clone());
252                true
253            }
254            _ => false,
255        }
256    }
257
258    pub fn is_empty(&self) -> bool {
259        if self.is_number() {
260            return false;
261        }
262        self.len() == 0
263    }
264
265    pub fn is_number(&self) -> bool {
266        match self {
267            Variant::Int8(_) |
268            Variant::UInt8(_) |
269            Variant::Int16(_) |
270            Variant::UInt16(_) |
271            Variant::Int32(_) |
272            Variant::UInt32(_) |
273            Variant::Int64(_) |
274            Variant::UInt64(_) |
275            Variant::Float(_) |
276            Variant::Double(_) => true,
277            _ => false,
278        }
279    }
280
281    pub fn set<T: Into<Self>>(&mut self, value: T) {
282        *self = value.into();
283    }
284
285    pub fn get<T: From<Self>>(&self) -> T {
286        T::from(self.clone())
287    }
288
289    pub fn get_number<T>(&self) -> Option<T>
290    where
291        T: FromPrimitive,
292    {
293        match self {
294            Variant::Int8(value) => T::from_i8(*value),
295            Variant::UInt8(value) => T::from_u8(*value),
296            Variant::Int16(value) => T::from_i16(*value),
297            Variant::UInt16(value) => T::from_u16(*value),
298            Variant::Int32(value) => T::from_i32(*value),
299            Variant::UInt32(value) => T::from_u32(*value),
300            Variant::Int64(value) => T::from_i64(*value),
301            Variant::UInt64(value) => T::from_u64(*value),
302            Variant::Float(value) => T::from_f32(*value),
303            Variant::Double(value) => T::from_f64(*value),
304            _ => None,
305        }
306    }
307
308    pub fn array_add(&mut self, value: Variant) {
309        match self {
310            Variant::Array(v) => {
311                v.push(value);
312            }
313            _ => (),
314        }
315    }
316
317    pub fn array_get(&self, index: usize) -> Option<Variant> {
318        match self {
319            Variant::Array(v) => v.get(index).cloned(),
320            _ => None,
321        }
322    }
323
324    pub fn array_set(&mut self, index: usize, value: Variant) {
325        match self {
326            Variant::Array(v) => {
327                if index >= v.len() {
328                    v.resize(index + 1, Variant::None);
329                }
330                v[index] = value;
331            }
332            _ => (),
333        }
334    }
335
336    pub fn array_remove(&mut self, index: usize) -> bool {
337        match self {
338            Variant::Array(v) => {
339                if index < v.len() {
340                    v.remove(index);
341                    true
342                } else {
343                    false
344                }
345            }
346            _ => false,
347        }
348    }
349
350    pub fn dict_get(&self, key: &str) -> Option<Variant> {
351        match self {
352            Variant::Dict(dict) => dict.get(key).cloned(),
353            _ => None,
354        }
355    }
356
357    pub fn dict_set(&mut self, key: &str, value: Variant) {
358        match self {
359            Variant::Dict(v) => {
360                v.insert(key.to_string(), value);
361            }
362            _ => (),
363        }
364    }
365
366    pub fn dict_remove(&mut self, key: &str) -> bool {
367        match self {
368            Variant::Dict(v) => v.remove(key).is_some(),
369            _ => false,
370        }
371    }
372
373    pub fn dict_contains(&self, key: &str) -> bool {
374        match self {
375            Variant::Dict(dict) => dict.contains_key(key),
376            _ => false,
377        }
378    }
379
380    pub fn array_iter(&self) -> Option<impl Iterator<Item = &Variant> + '_> {
381        match self {
382            Variant::Array(array) => Some(array.iter()),
383            _ => None,
384        }
385    }
386
387    pub fn array_iter_mut(&mut self) -> Option<impl Iterator<Item = &mut Variant> + '_> {
388        match self {
389            Variant::Array(array) => Some(array.iter_mut()),
390            _ => None,
391        }
392    }
393
394    pub fn dict_iter(&self) -> Option<impl Iterator<Item = (&String, &Variant)> + '_> {
395        match self {
396            Variant::Dict(dict) => Some(dict.iter()),
397            _ => None,
398        }
399    }
400
401    pub fn dict_iter_mut(&mut self) -> Option<impl Iterator<Item = (&String, &mut Variant)> + '_> {
402        match self {
403            Variant::Dict(dict) => Some(dict.iter_mut()),
404            _ => None,
405        }
406    }
407
408    variant_getters! {
409        (get_bool, Bool, bool),
410        (get_string, String, String),
411        (get_buffer, Buffer, Vec<u8>)
412    }
413
414    variant_number_getters! {
415        (get_int8, Int8, i8),
416        (get_uint8, UInt8, u8),
417        (get_int16, Int16, i16),
418        (get_uint16, UInt16, u16),
419        (get_int32, Int32, i32),
420        (get_uint32, UInt32, u32),
421        (get_int64, Int64, i64),
422        (get_uint64, UInt64, u64),
423        (get_float, Float, f32),
424        (get_double, Double, f64)
425    }
426
427    variant_methods! {
428        (get_bool, set_bool, array_add_bool, array_get_bool, array_set_bool, dict_set_bool, dict_get_bool, Bool, bool),
429        (get_int8, set_int8, array_add_int8, array_get_int8, array_set_int8, dict_set_int8, dict_get_int8, Int8, i8),
430        (get_uint8, set_uint8, array_add_uint8, array_get_uint8, array_set_uint8, dict_set_uint8, dict_get_uint8, UInt8, u8),
431        (get_int16, set_int16, array_add_int16, array_get_int16, array_set_int16, dict_set_int16, dict_get_int16, Int16, i16),
432        (get_uint16, set_uint16, array_add_uint16, array_get_uint16, array_set_uint16, dict_set_uint16, dict_get_uint16, UInt16, u16),
433        (get_int32, set_int32, array_add_int32, array_get_int32, array_set_int32, dict_set_int32, dict_get_int32, Int32, i32),
434        (get_uint32, set_uint32, array_add_uint32, array_get_uint32, array_set_uint32, dict_set_uint32, dict_get_uint32, UInt32, u32),
435        (get_int64, set_int64, array_add_int64, array_get_int64, array_set_int64, dict_set_int64, dict_get_int64, Int64, i64),
436        (get_uint64, set_uint64, array_add_uint64, array_get_uint64, array_set_uint64, dict_set_uint64, dict_get_uint64, UInt64, u64),
437        (get_float, set_float, array_add_float, array_get_float, array_set_float, dict_set_float, dict_get_float, Float, f32),
438        (get_double, set_double, array_add_double, array_get_double, array_set_double, dict_set_double, dict_get_double, Double, f64),
439        (get_string, set_string, array_add_string, array_get_string, array_set_string, dict_set_string, dict_get_string, String, String),
440        (get_buffer, set_buffer, array_add_buffer, array_get_buffer, array_set_buffer, dict_set_buffer, dict_get_buffer, Buffer, Vec<u8>)
441    }
442}
443
444impl Index<usize> for Variant {
445    type Output = Variant;
446
447    fn index(&self, index: usize) -> &Self::Output {
448        match self {
449            Variant::Array(v) => v.get(index).unwrap_or(&Variant::None),
450            _ => &Variant::None,
451        }
452    }
453}
454
455impl IndexMut<usize> for Variant {
456    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
457        match self {
458            Variant::Array(array) => {
459                if index >= array.len() {
460                    array.resize(index + 1, Variant::None);
461                }
462                &mut array[index]
463            }
464            _ => {
465                *self = Variant::Array(Vec::new());
466                self.index_mut(index)
467            }
468        }
469    }
470}
471
472impl Index<&str> for Variant {
473    type Output = Variant;
474
475    fn index(&self, index: &str) -> &Self::Output {
476        match self {
477            Variant::Dict(v) => v.get(index).unwrap_or(&Variant::None),
478            _ => &Variant::None,
479        }
480    }
481}
482
483impl IndexMut<&str> for Variant {
484    fn index_mut(&mut self, index: &str) -> &mut Self::Output {
485        match self {
486            Variant::Dict(dict) => dict.entry(index.to_string()).or_insert(Variant::None),
487            _ => {
488                *self = Variant::Dict(HashMap::new());
489                self.index_mut(index)
490            }
491        }
492    }
493}
494
495impl FromIterator<Variant> for Variant {
496    fn from_iter<I: IntoIterator<Item = Variant>>(iter: I) -> Self {
497        Variant::Array(iter.into_iter().collect())
498    }
499}
500
501impl FromIterator<(String, Variant)> for Variant {
502    fn from_iter<I: IntoIterator<Item = (String, Variant)>>(iter: I) -> Self {
503        Variant::Dict(iter.into_iter().collect())
504    }
505}
506
507#[derive(Clone)]
508pub struct SharedVariant {
509    inner: Arc<RwLock<Variant>>,
510}
511
512impl From<Variant> for SharedVariant {
513    fn from(variant: Variant) -> Self {
514        SharedVariant {
515            inner: Arc::new(RwLock::new(variant)),
516        }
517    }
518}
519
520macro_rules! shared_variant_from_traits {
521    ($(($value_type:ty)),+) => {
522        $(
523            impl From<$value_type> for SharedVariant {
524                fn from(value: $value_type) -> Self {
525                    Variant::from(value).into()
526                }
527            }
528        )+
529    };
530}
531
532shared_variant_from_traits! {
533    (bool),
534    (i8),
535    (u8),
536    (i16),
537    (u16),
538    (i32),
539    (u32),
540    (i64),
541    (u64),
542    (f32),
543    (f64),
544    (String),
545    (Vec<u8>),
546    (Vec<Variant>),
547    (HashMap<String, Variant>)
548}
549
550impl SharedVariant {
551    pub fn inner(&self) -> Arc<RwLock<Variant>> {
552        self.inner.clone()
553    }
554}