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}