plugx_input/
input.rs

1use serde::{Deserialize, Serialize};
2use std::{
3    collections::HashMap,
4    fmt::{Debug, Display, Formatter},
5};
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(
9    untagged,
10    expecting = "expecting boolean, integer, float, string, list, or map"
11)]
12pub enum Input {
13    Bool(bool),
14    Int(isize),
15    Float(f64),
16    Str(String),
17    List(Vec<Input>),
18    Map(HashMap<String, Input>),
19}
20
21impl Input {
22    pub fn new_map() -> Self {
23        Self::Map(HashMap::new())
24    }
25
26    pub fn new_list() -> Self {
27        Self::List(Vec::new())
28    }
29
30    pub fn new_str() -> Self {
31        Self::Str(String::new())
32    }
33
34    pub fn is_bool(&self) -> bool {
35        matches!(self, Self::Bool(_))
36    }
37
38    pub fn as_bool(&self) -> &bool {
39        if let Self::Bool(value) = self {
40            value
41        } else {
42            panic!("Expected Input to be a boolean. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
43        }
44    }
45
46    pub fn into_bool(self) -> bool {
47        if let Self::Bool(value) = self {
48            value
49        } else {
50            panic!("Expected Input to be a boolean. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
51        }
52    }
53
54    pub fn bool_mut(&mut self) -> &mut bool {
55        if let Self::Bool(value) = self {
56            value
57        } else {
58            panic!("Expected Input to be a boolean. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
59        }
60    }
61
62    pub fn is_int(&self) -> bool {
63        matches!(self, Self::Int(_))
64    }
65
66    pub fn as_int(&self) -> &isize {
67        if let Self::Int(value) = self {
68            value
69        } else {
70            panic!("Expected Input to be a integer. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
71        }
72    }
73
74    pub fn into_int(self) -> isize {
75        if let Self::Int(value) = self {
76            value
77        } else {
78            panic!("Expected Input to be a integer. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
79        }
80    }
81
82    pub fn int_mut(&mut self) -> &mut isize {
83        if let Self::Int(value) = self {
84            value
85        } else {
86            panic!("Expected Input to be a integer. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
87        }
88    }
89
90    pub fn is_float(&self) -> bool {
91        matches!(self, Self::Float(_))
92    }
93
94    pub fn as_float(&self) -> &f64 {
95        if let Self::Float(value) = self {
96            value
97        } else {
98            panic!("Expected Input to be a float. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
99        }
100    }
101
102    pub fn into_float(self) -> f64 {
103        if let Self::Float(value) = self {
104            value
105        } else {
106            panic!("Expected Input to be a float. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
107        }
108    }
109
110    pub fn float_mut(&mut self) -> &mut f64 {
111        if let Self::Float(value) = self {
112            value
113        } else {
114            panic!("Expected Input to be a float. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
115        }
116    }
117
118    pub fn is_str(&self) -> bool {
119        matches!(self, Self::Str(_))
120    }
121
122    pub fn as_str(&self) -> &String {
123        if let Self::Str(value) = self {
124            value
125        } else {
126            panic!("Expected Input to be a string. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
127        }
128    }
129
130    pub fn into_str(self) -> String {
131        if let Self::Str(value) = self {
132            value
133        } else {
134            panic!("Expected Input to be a string. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
135        }
136    }
137
138    pub fn str_mut(&mut self) -> &mut String {
139        if let Self::Str(value) = self {
140            value
141        } else {
142            panic!("Expected Input to be a string. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
143        }
144    }
145
146    pub fn is_list(&self) -> bool {
147        matches!(self, Self::List(_))
148    }
149
150    pub fn as_list(&self) -> &Vec<Input> {
151        if let Self::List(value) = self {
152            value
153        } else {
154            panic!("Expected Input to be a list. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
155        }
156    }
157
158    pub fn into_list(self) -> Vec<Input> {
159        if let Self::List(value) = self {
160            value
161        } else {
162            panic!("Expected Input to be a list. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
163        }
164    }
165
166    pub fn list_mut(&mut self) -> &mut Vec<Input> {
167        if let Self::List(value) = self {
168            value
169        } else {
170            panic!("Expected Input to be a list. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
171        }
172    }
173
174    pub fn is_map(&self) -> bool {
175        matches!(self, Self::Map(_))
176    }
177
178    pub fn as_map(&self) -> &HashMap<String, Input> {
179        if let Self::Map(value) = self {
180            value
181        } else {
182            panic!("Expected Input to be a map. You should call `.is_<TYPE>()` before calling any `as_<TYPE>()` method")
183        }
184    }
185
186    pub fn into_map(self) -> HashMap<String, Input> {
187        if let Self::Map(value) = self {
188            value
189        } else {
190            panic!("Expected Input to be a map. You should call `.is_<TYPE>()` before calling any `into_<TYPE>()` method")
191        }
192    }
193
194    pub fn map_mut(&mut self) -> &mut HashMap<String, Input> {
195        if let Self::Map(value) = self {
196            value
197        } else {
198            panic!("Expected Input to be a map. You should call `.is_<TYPE>()` before calling any `<TYPE>_mut()` method")
199        }
200    }
201
202    pub fn type_name(&self) -> String {
203        match self {
204            Self::Bool(_) => Self::bool_type_name(),
205            Self::Int(_) => Self::int_type_name(),
206            Self::Float(_) => Self::float_type_name(),
207            Self::Str(_) => Self::str_type_name(),
208            Self::List(_) => Self::list_type_name(),
209            Self::Map(_) => Self::map_type_name(),
210        }
211    }
212
213    pub fn map_type_name() -> String {
214        "map".to_string()
215    }
216
217    pub fn list_type_name() -> String {
218        "list".to_string()
219    }
220
221    pub fn str_type_name() -> String {
222        "string".to_string()
223    }
224
225    pub fn int_type_name() -> String {
226        "integer".to_string()
227    }
228
229    pub fn float_type_name() -> String {
230        "float".to_string()
231    }
232
233    pub fn bool_type_name() -> String {
234        "boolean".to_string()
235    }
236}
237
238impl Display for Input {
239    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
240        match self {
241            Self::Bool(value) => write!(f, "{value}"),
242            Self::Int(value) => write!(f, "{value}"),
243            Self::Float(value) => write!(f, "{value}"),
244            Self::Str(value) => write!(f, "{value:?}"),
245            Self::List(value) => {
246                write!(f, "[")?;
247                let length = value.len();
248                for (index, inner_value) in value.iter().enumerate() {
249                    write!(f, "{inner_value}")?;
250                    if index < length - 1 {
251                        write!(f, ", ")?;
252                    }
253                }
254                write!(f, "]")
255            }
256            Self::Map(value) => {
257                write!(f, "{{")?;
258                let length = value.len();
259                for (index, (key, value)) in value.iter().enumerate() {
260                    write!(f, "{key:?}: {value}")?;
261                    if index < length - 1 {
262                        write!(f, ", ")?;
263                    }
264                }
265                write!(f, "}}")
266            }
267        }
268    }
269}
270
271#[cfg(test)]
272mod tests {
273    use super::*;
274    use std::collections::HashMap;
275
276    #[test]
277    fn serde() {
278        let de_result = serde_json::from_str::<Input>("true");
279        assert!(de_result.is_ok());
280        assert_eq!(Input::Bool(true), de_result.unwrap());
281
282        let de_result = serde_json::from_str::<Input>("0");
283        assert!(de_result.is_ok());
284        assert_eq!(Input::Int(0), de_result.unwrap());
285        let de_result = serde_json::from_str::<Input>("1234567890");
286        assert!(de_result.is_ok());
287        assert_eq!(Input::Int(1234567890), de_result.unwrap());
288        let de_result = serde_json::from_str::<Input>("-1234567890");
289        assert!(de_result.is_ok());
290        assert_eq!(Input::Int(-1234567890), de_result.unwrap());
291
292        let de_result = serde_json::from_str::<Input>("0.0");
293        assert!(de_result.is_ok());
294        assert_eq!(Input::Float(0.0), de_result.unwrap());
295        let de_result = serde_json::from_str::<Input>("1234567890.0");
296        assert!(de_result.is_ok());
297        assert_eq!(Input::Float(1234567890.0), de_result.unwrap());
298        let de_result = serde_json::from_str::<Input>("-1234567890.0");
299        assert!(de_result.is_ok());
300        assert_eq!(Input::Float(-1234567890.0), de_result.unwrap());
301
302        let de_result = serde_json::from_str::<Input>("\"hello\"");
303        assert!(de_result.is_ok());
304        assert_eq!(Input::Str("hello".to_string()), de_result.unwrap());
305        let de_result = serde_json::from_str::<Input>("\"false\"");
306        assert!(de_result.is_ok());
307        assert_eq!(Input::Str("false".to_string()), de_result.unwrap());
308        let de_result = serde_json::from_str::<Input>("\"1\"");
309        assert!(de_result.is_ok());
310        assert_eq!(Input::Str("1".to_string()), de_result.unwrap());
311        let de_result = serde_json::from_str::<Input>("\"3.14\"");
312        assert!(de_result.is_ok());
313        assert_eq!(Input::Str("3.14".to_string()), de_result.unwrap());
314
315        let de_result = serde_json::from_str::<Input>("[false, 0, 0.0, \"hello\", [[]], {}]");
316        assert!(de_result.is_ok());
317        let list = de_result.unwrap();
318        assert!(list.is_list());
319        assert_eq!(
320            Input::List(
321                [
322                    Input::from(false),
323                    Input::from(0),
324                    Input::from(0.0),
325                    Input::from("hello".to_string()),
326                    Input::from([Input::List([].to_vec())].to_vec()),
327                    Input::from(Input::new_map())
328                ]
329                .to_vec()
330            ),
331            list
332        );
333
334        let de_result = serde_json::from_str::<Input>(
335            "{\"foo\": 0, \"bar\": 0.0, \"baz\": false, \"qux\": {\"hello\": \"world\"}}",
336        );
337        assert!(de_result.is_ok());
338        let map = de_result.unwrap();
339        assert!(map.is_map());
340        assert_eq!(
341            Input::Map(HashMap::from([
342                ("foo".to_string(), Input::Int(0)),
343                ("bar".to_string(), Input::Float(0.0)),
344                ("baz".to_string(), Input::Bool(false)),
345                (
346                    "qux".to_string(),
347                    Input::Map(HashMap::from([(
348                        "hello".to_string(),
349                        Input::Str("world".to_string())
350                    )]))
351                ),
352            ])),
353            map
354        );
355    }
356}