1use std::cmp::Ordering;
2use std::collections::{BTreeMap, HashMap};
3use std::hash::{Hash, Hasher};
4
5use ordered_float::OrderedFloat;
6
7#[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}