valence_command/
modifier_value.rs

1use std::cmp::Ordering;
2use std::collections::{BTreeMap, HashMap};
3use std::hash::{Hash, Hasher};
4
5use ordered_float::OrderedFloat;
6
7/// Used to store keys values for command modifiers. Heavily inspired by
8/// serde-value.
9#[derive(Clone, Debug)]
10pub enum ModifierValue {
11    Bool(bool),
12
13    U8(u8),
14    U16(u16),
15    U32(u32),
16    U64(u64),
17
18    I8(i8),
19    I16(i16),
20    I32(i32),
21    I64(i64),
22
23    F32(f32),
24    F64(f64),
25
26    Char(char),
27    String(String),
28
29    Unit,
30    Option(Option<Box<ModifierValue>>),
31    Seq(Vec<ModifierValue>),
32    Map(BTreeMap<ModifierValue, ModifierValue>),
33}
34
35#[allow(clippy::unit_hash)]
36impl Hash for ModifierValue {
37    fn hash<H>(&self, hasher: &mut H)
38    where
39        H: Hasher,
40    {
41        self.discriminant().hash(hasher);
42        match self {
43            ModifierValue::Bool(v) => v.hash(hasher),
44            ModifierValue::U8(v) => v.hash(hasher),
45            ModifierValue::U16(v) => v.hash(hasher),
46            ModifierValue::U32(v) => v.hash(hasher),
47            ModifierValue::U64(v) => v.hash(hasher),
48            ModifierValue::I8(v) => v.hash(hasher),
49            ModifierValue::I16(v) => v.hash(hasher),
50            ModifierValue::I32(v) => v.hash(hasher),
51            ModifierValue::I64(v) => v.hash(hasher),
52            ModifierValue::F32(v) => OrderedFloat(*v).hash(hasher),
53            ModifierValue::F64(v) => OrderedFloat(*v).hash(hasher),
54            ModifierValue::Char(v) => v.hash(hasher),
55            ModifierValue::String(v) => v.hash(hasher),
56            ModifierValue::Unit => ().hash(hasher),
57            ModifierValue::Option(v) => v.hash(hasher),
58            ModifierValue::Seq(v) => v.hash(hasher),
59            ModifierValue::Map(v) => v.hash(hasher),
60        }
61    }
62}
63
64impl PartialEq for ModifierValue {
65    fn eq(&self, rhs: &Self) -> bool {
66        match (self, rhs) {
67            (&ModifierValue::Bool(v0), &ModifierValue::Bool(v1)) if v0 == v1 => true,
68            (&ModifierValue::U8(v0), &ModifierValue::U8(v1)) if v0 == v1 => true,
69            (&ModifierValue::U16(v0), &ModifierValue::U16(v1)) if v0 == v1 => true,
70            (&ModifierValue::U32(v0), &ModifierValue::U32(v1)) if v0 == v1 => true,
71            (&ModifierValue::U64(v0), &ModifierValue::U64(v1)) if v0 == v1 => true,
72            (&ModifierValue::I8(v0), &ModifierValue::I8(v1)) if v0 == v1 => true,
73            (&ModifierValue::I16(v0), &ModifierValue::I16(v1)) if v0 == v1 => true,
74            (&ModifierValue::I32(v0), &ModifierValue::I32(v1)) if v0 == v1 => true,
75            (&ModifierValue::I64(v0), &ModifierValue::I64(v1)) if v0 == v1 => true,
76            (&ModifierValue::F32(v0), &ModifierValue::F32(v1))
77                if OrderedFloat(v0) == OrderedFloat(v1) =>
78            {
79                true
80            }
81            (&ModifierValue::F64(v0), &ModifierValue::F64(v1))
82                if OrderedFloat(v0) == OrderedFloat(v1) =>
83            {
84                true
85            }
86            (&ModifierValue::Char(v0), &ModifierValue::Char(v1)) if v0 == v1 => true,
87            (ModifierValue::String(v0), ModifierValue::String(v1)) if v0 == v1 => true,
88            (ModifierValue::Unit, ModifierValue::Unit) => true,
89            (ModifierValue::Option(v0), ModifierValue::Option(v1)) if v0 == v1 => true,
90            (ModifierValue::Seq(v0), ModifierValue::Seq(v1)) if v0 == v1 => true,
91            (ModifierValue::Map(v0), ModifierValue::Map(v1)) if v0 == v1 => true,
92            _ => false,
93        }
94    }
95}
96
97impl Ord for ModifierValue {
98    fn cmp(&self, rhs: &Self) -> Ordering {
99        match (self, rhs) {
100            (&ModifierValue::Bool(v0), ModifierValue::Bool(v1)) => v0.cmp(v1),
101            (&ModifierValue::U8(v0), ModifierValue::U8(v1)) => v0.cmp(v1),
102            (&ModifierValue::U16(v0), ModifierValue::U16(v1)) => v0.cmp(v1),
103            (&ModifierValue::U32(v0), ModifierValue::U32(v1)) => v0.cmp(v1),
104            (&ModifierValue::U64(v0), ModifierValue::U64(v1)) => v0.cmp(v1),
105            (&ModifierValue::I8(v0), ModifierValue::I8(v1)) => v0.cmp(v1),
106            (&ModifierValue::I16(v0), ModifierValue::I16(v1)) => v0.cmp(v1),
107            (&ModifierValue::I32(v0), ModifierValue::I32(v1)) => v0.cmp(v1),
108            (&ModifierValue::I64(v0), ModifierValue::I64(v1)) => v0.cmp(v1),
109            (&ModifierValue::F32(v0), &ModifierValue::F32(v1)) => {
110                OrderedFloat(v0).cmp(&OrderedFloat(v1))
111            }
112            (&ModifierValue::F64(v0), &ModifierValue::F64(v1)) => {
113                OrderedFloat(v0).cmp(&OrderedFloat(v1))
114            }
115            (ModifierValue::Char(v0), ModifierValue::Char(v1)) => v0.cmp(v1),
116            (ModifierValue::String(v0), ModifierValue::String(v1)) => v0.cmp(v1),
117            (ModifierValue::Unit, &ModifierValue::Unit) => Ordering::Equal,
118            (ModifierValue::Option(v0), ModifierValue::Option(v1)) => v0.cmp(v1),
119            (ModifierValue::Seq(v0), ModifierValue::Seq(v1)) => v0.cmp(v1),
120            (ModifierValue::Map(v0), ModifierValue::Map(v1)) => v0.cmp(v1),
121            (v0, v1) => v0.discriminant().cmp(&v1.discriminant()),
122        }
123    }
124}
125
126impl ModifierValue {
127    fn discriminant(&self) -> usize {
128        match *self {
129            ModifierValue::Bool(..) => 0,
130            ModifierValue::U8(..) => 1,
131            ModifierValue::U16(..) => 2,
132            ModifierValue::U32(..) => 3,
133            ModifierValue::U64(..) => 4,
134            ModifierValue::I8(..) => 5,
135            ModifierValue::I16(..) => 6,
136            ModifierValue::I32(..) => 7,
137            ModifierValue::I64(..) => 8,
138            ModifierValue::F32(..) => 9,
139            ModifierValue::F64(..) => 10,
140            ModifierValue::Char(..) => 11,
141            ModifierValue::String(..) => 12,
142            ModifierValue::Unit => 13,
143            ModifierValue::Option(..) => 14,
144            ModifierValue::Seq(..) => 16,
145            ModifierValue::Map(..) => 17,
146        }
147    }
148}
149
150impl Eq for ModifierValue {}
151impl PartialOrd for ModifierValue {
152    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
153        Some(self.cmp(rhs))
154    }
155}
156
157macro_rules! impl_from {
158    ($ty:ty, $variant:ident) => {
159        impl From<$ty> for ModifierValue {
160            fn from(v: $ty) -> Self {
161                ModifierValue::$variant(v)
162            }
163        }
164    };
165}
166
167impl_from!(bool, Bool);
168
169impl_from!(u8, U8);
170impl_from!(u16, U16);
171impl_from!(u32, U32);
172impl_from!(u64, U64);
173
174impl_from!(i8, I8);
175impl_from!(i16, I16);
176impl_from!(i32, I32);
177impl_from!(i64, I64);
178
179impl_from!(f32, F32);
180impl_from!(f64, F64);
181
182impl_from!(char, Char);
183impl_from!(String, String);
184
185impl From<&str> for ModifierValue {
186    fn from(v: &str) -> Self {
187        ModifierValue::String(v.to_owned())
188    }
189}
190
191impl From<()> for ModifierValue {
192    fn from((): ()) -> Self {
193        ModifierValue::Unit
194    }
195}
196
197impl From<Option<ModifierValue>> for ModifierValue {
198    fn from(v: Option<ModifierValue>) -> Self {
199        ModifierValue::Option(v.map(Box::new))
200    }
201}
202
203impl<T: Into<ModifierValue>> From<Vec<T>> for ModifierValue {
204    fn from(v: Vec<T>) -> Self {
205        ModifierValue::Seq(v.into_iter().map(Into::into).collect())
206    }
207}
208
209impl<K: Into<ModifierValue>, V: Into<ModifierValue>> From<BTreeMap<K, V>> for ModifierValue {
210    fn from(v: BTreeMap<K, V>) -> Self {
211        ModifierValue::Map(v.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
212    }
213}
214
215impl<K: Into<ModifierValue>, V: Into<ModifierValue>> From<HashMap<K, V>> for ModifierValue {
216    fn from(v: HashMap<K, V>) -> Self {
217        ModifierValue::Map(v.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
218    }
219}