1use std::{
2 cmp::Ordering,
3 ffi::OsString,
4 fmt::{Debug, Display},
5 path::PathBuf,
6};
7
8use serde::{
9 de::{Error as SError, SeqAccess, Visitor},
10 Deserialize, Deserializer, Serialize,
11};
12
13#[derive(Clone, PartialEq, PartialOrd)]
14pub enum Value {
15 Null,
16 String(String),
17 Number(Number),
18 List(Vec<Value>),
19}
20
21#[derive(Clone, PartialEq, PartialOrd)]
22pub struct Number {
23 inner: NumberVariant,
24}
25
26#[derive(Clone, Copy)]
27enum NumberVariant {
28 Unsigned(u64),
29 Signed(i64),
30 Float(f64),
31}
32
33impl Serialize for Value {
34 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35 where
36 S: serde::Serializer,
37 {
38 match self {
39 Value::Null => serializer.serialize_unit(),
40 Value::Number(n) => n.serialize(serializer),
41 Value::String(s) => serializer.serialize_str(s),
42 Value::List(seq) => seq.serialize(serializer),
43 }
44 }
45}
46
47impl Serialize for Number {
48 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
49 where
50 S: serde::Serializer,
51 {
52 {
53 match self.inner {
54 NumberVariant::Unsigned(u) => serializer.serialize_u64(u),
55 NumberVariant::Signed(s) => serializer.serialize_i64(s),
56 NumberVariant::Float(f) => serializer.serialize_f64(f),
57 }
58 }
59 }
60}
61
62impl<'de> Deserialize<'de> for Value {
63 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
64 where
65 D: serde::Deserializer<'de>,
66 {
67 struct ValueVisitor;
68
69 impl<'de> Visitor<'de> for ValueVisitor {
70 type Value = Value;
71
72 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
73 formatter.write_str("any comtrya context value")
74 }
75
76 fn visit_i64<E>(self, i: i64) -> Result<Value, E>
77 where
78 E: SError,
79 {
80 Ok(Value::Number(Number {
81 inner: NumberVariant::Signed(i),
82 }))
83 }
84
85 fn visit_u64<E>(self, u: u64) -> Result<Value, E>
86 where
87 E: SError,
88 {
89 Ok(Value::Number(Number {
90 inner: NumberVariant::Unsigned(u),
91 }))
92 }
93
94 fn visit_f64<E>(self, f: f64) -> Result<Value, E>
95 where
96 E: SError,
97 {
98 Ok(Value::Number(Number {
99 inner: NumberVariant::Float(f),
100 }))
101 }
102
103 fn visit_str<E>(self, s: &str) -> Result<Value, E>
104 where
105 E: SError,
106 {
107 Ok(Value::String(s.to_owned()))
108 }
109
110 fn visit_string<E>(self, s: String) -> Result<Value, E>
111 where
112 E: SError,
113 {
114 Ok(Value::String(s))
115 }
116
117 fn visit_unit<E>(self) -> Result<Value, E>
118 where
119 E: SError,
120 {
121 Ok(Value::Null)
122 }
123
124 fn visit_none<E>(self) -> Result<Value, E>
125 where
126 E: SError,
127 {
128 Ok(Value::Null)
129 }
130
131 fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
132 where
133 D: Deserializer<'de>,
134 {
135 Deserialize::deserialize(deserializer)
136 }
137
138 fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
139 where
140 V: SeqAccess<'de>,
141 {
142 let mut vec = Vec::new();
143
144 while let Some(element) = visitor.next_element()? {
145 vec.push(element);
146 }
147
148 Ok(Value::List(vec))
149 }
150 }
151
152 deserializer.deserialize_any(ValueVisitor)
153 }
154}
155
156impl Debug for Value {
157 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 match self {
159 Value::Null => formatter.write_str("Null"),
160 Value::String(string) => write!(formatter, "String({:?})", string),
161 Value::Number(number) => write!(formatter, "Number({})", number),
162 Value::List(list) => {
163 formatter.write_str("List ")?;
164 formatter.debug_list().entries(list).finish()
165 }
166 }
167 }
168}
169
170impl Debug for Number {
171 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 write!(formatter, "Number({})", self)
173 }
174}
175
176impl Display for Number {
177 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178 match self.inner {
179 NumberVariant::Unsigned(number) => Display::fmt(&number, formatter),
180 NumberVariant::Signed(number) => Display::fmt(&number, formatter),
181 NumberVariant::Float(number) => Display::fmt(&number, formatter),
182 }
183 }
184}
185
186impl NumberVariant {
187 fn total_cmp(&self, other: &Self) -> Ordering {
188 match (*self, *other) {
189 (NumberVariant::Unsigned(a), NumberVariant::Unsigned(b)) => a.cmp(&b),
190 (NumberVariant::Signed(a), NumberVariant::Signed(b)) => a.cmp(&b),
191 (NumberVariant::Unsigned(a), NumberVariant::Signed(b)) => (a as i64).cmp(&b),
192 (NumberVariant::Signed(a), NumberVariant::Unsigned(b)) => a.cmp(&(b as i64)),
193 (NumberVariant::Float(a), NumberVariant::Float(b)) => {
194 a.partial_cmp(&b).unwrap_or_else(|| {
196 if !a.is_nan() {
198 Ordering::Less
199 } else if !b.is_nan() {
200 Ordering::Greater
201 } else {
202 Ordering::Equal
203 }
204 })
205 }
206 (NumberVariant::Signed(a), NumberVariant::Float(b)) => {
207 (a as f64).partial_cmp(&b).unwrap_or_else(|| {
209 if !(a as f64).is_nan() {
211 Ordering::Less
212 } else if !b.is_nan() {
213 Ordering::Greater
214 } else {
215 Ordering::Equal
216 }
217 })
218 }
219 (NumberVariant::Unsigned(a), NumberVariant::Float(b)) => {
220 (a as f64).partial_cmp(&b).unwrap_or_else(|| {
222 if !(a as f64).is_nan() {
224 Ordering::Less
225 } else if !b.is_nan() {
226 Ordering::Greater
227 } else {
228 Ordering::Equal
229 }
230 })
231 }
232 (NumberVariant::Float(a), NumberVariant::Signed(b)) => {
233 a.partial_cmp(&(b as f64)).unwrap_or_else(|| {
235 if !a.is_nan() {
237 Ordering::Less
238 } else if !(b as f64).is_nan() {
239 Ordering::Greater
240 } else {
241 Ordering::Equal
242 }
243 })
244 }
245 (NumberVariant::Float(a), NumberVariant::Unsigned(b)) => {
246 a.partial_cmp(&(b as f64)).unwrap_or_else(|| {
248 if !a.is_nan() {
250 Ordering::Less
251 } else if !(b as f64).is_nan() {
252 Ordering::Greater
253 } else {
254 Ordering::Equal
255 }
256 })
257 }
258 }
259 }
260}
261
262impl PartialEq for NumberVariant {
263 fn eq(&self, other: &Self) -> bool {
264 match (*self, *other) {
265 (NumberVariant::Unsigned(a), NumberVariant::Unsigned(b)) => a == b,
266 (NumberVariant::Signed(a), NumberVariant::Signed(b)) => a == b,
267 (NumberVariant::Float(a), NumberVariant::Float(b)) => a == b,
268 (NumberVariant::Unsigned(a), NumberVariant::Signed(b)) => (a as i64) == b,
269 (NumberVariant::Signed(a), NumberVariant::Unsigned(b)) => a == (b as i64),
270 (NumberVariant::Unsigned(a), NumberVariant::Float(b)) => (a as f64) == b,
271 (NumberVariant::Signed(a), NumberVariant::Float(b)) => (a as f64) == b,
272 (NumberVariant::Float(a), NumberVariant::Unsigned(b)) => a == (b as f64),
273 (NumberVariant::Float(a), NumberVariant::Signed(b)) => a == (b as f64),
274 }
275 }
276}
277
278impl PartialOrd for NumberVariant {
279 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
280 Some(self.total_cmp(other))
281 }
282}
283
284impl From<String> for Value {
285 fn from(from: String) -> Self {
286 Value::String(from)
287 }
288}
289
290impl<'a> From<&'a str> for Value {
291 fn from(from: &'a str) -> Self {
292 Value::String(from.to_string())
293 }
294}
295
296impl<'a> From<std::borrow::Cow<'a, str>> for Value {
297 fn from(from: std::borrow::Cow<'a, str>) -> Self {
298 Value::String(from.to_string())
299 }
300}
301
302impl From<OsString> for Value {
303 fn from(from: OsString) -> Self {
304 Value::String(from.to_str().unwrap_or("unknown").to_string())
305 }
306}
307
308impl From<PathBuf> for Value {
309 fn from(from: PathBuf) -> Self {
310 Value::String(from.display().to_string())
311 }
312}
313
314impl<T: Into<Value>> From<Vec<T>> for Value {
315 fn from(from: Vec<T>) -> Self {
316 Value::List(from.into_iter().map(Into::into).collect())
317 }
318}
319
320impl ToString for Value {
321 fn to_string(&self) -> String {
322 match self {
323 Value::Null => "null".to_string(),
324 Value::String(string) => string.to_owned(),
325 Value::Number(number) => number.to_string(),
326 Value::List(list) => list
327 .iter()
328 .map(|value| value.to_string())
329 .collect::<Vec<String>>()
330 .join(","),
331 }
332 }
333}
334
335#[cfg(test)]
336mod test {
337 use std::{borrow::Cow, ffi::OsString, path::PathBuf};
338
339 use crate::values::{Number, NumberVariant, Value};
340 use anyhow::Ok;
341 use pretty_assertions::assert_eq;
342
343 #[test]
344 fn from_string_tests() -> anyhow::Result<()> {
345 assert_eq!(
346 Value::from("John Sheppard"),
347 Value::String("John Sheppard".to_string())
348 );
349
350 assert_eq!(
351 Value::from("Elizabeth Weir".to_string()),
352 Value::String("Elizabeth Weir".to_string())
353 );
354
355 assert_eq!(Value::from(PathBuf::new()), Value::String("".to_string()));
356
357 assert_eq!(
358 Value::from(Cow::from("Samantha Carter")),
359 Value::String("Samantha Carter".to_string())
360 );
361
362 assert_eq!(
363 Value::from(OsString::from("Jennifer Keller")),
364 Value::String("Jennifer Keller".to_string())
365 );
366
367 Ok(())
368 }
369
370 #[test]
371 fn from_vec_test() -> anyhow::Result<()> {
372 assert_eq!(
373 Value::from(vec!["Aiden Ford", "Rodney McKay", "Ronon Dex"]),
374 Value::List(vec![
375 Value::String("Aiden Ford".to_string()),
376 Value::String("Rodney McKay".to_string()),
377 Value::String("Ronon Dex".to_string())
378 ])
379 );
380
381 Ok(())
382 }
383
384 #[test]
385 fn number_compare_test() -> anyhow::Result<()> {
386 assert_eq!(
388 true,
389 Value::Number(Number {
390 inner: NumberVariant::Unsigned(2)
391 }) == Value::Number(Number {
392 inner: NumberVariant::Unsigned(2)
393 })
394 );
395
396 assert_eq!(
397 true,
398 Value::Number(Number {
399 inner: NumberVariant::Unsigned(3)
400 }) > Value::Number(Number {
401 inner: NumberVariant::Unsigned(2)
402 })
403 );
404
405 assert_eq!(
406 true,
407 Value::Number(Number {
408 inner: NumberVariant::Unsigned(2)
409 }) < Value::Number(Number {
410 inner: NumberVariant::Unsigned(3)
411 })
412 );
413
414 assert_eq!(
416 true,
417 Value::Number(Number {
418 inner: NumberVariant::Signed(2)
419 }) == Value::Number(Number {
420 inner: NumberVariant::Signed(2)
421 })
422 );
423
424 assert_eq!(
425 true,
426 Value::Number(Number {
427 inner: NumberVariant::Signed(3)
428 }) > Value::Number(Number {
429 inner: NumberVariant::Signed(2)
430 })
431 );
432
433 assert_eq!(
434 true,
435 Value::Number(Number {
436 inner: NumberVariant::Signed(2)
437 }) < Value::Number(Number {
438 inner: NumberVariant::Signed(3)
439 })
440 );
441
442 assert_eq!(
444 true,
445 Value::Number(Number {
446 inner: NumberVariant::Float(2.0)
447 }) == Value::Number(Number {
448 inner: NumberVariant::Float(2.0)
449 })
450 );
451
452 assert_eq!(
453 true,
454 Value::Number(Number {
455 inner: NumberVariant::Float(3.0)
456 }) > Value::Number(Number {
457 inner: NumberVariant::Float(2.0)
458 })
459 );
460
461 assert_eq!(
462 true,
463 Value::Number(Number {
464 inner: NumberVariant::Float(2.0)
465 }) < Value::Number(Number {
466 inner: NumberVariant::Float(3.0)
467 })
468 );
469
470 assert_eq!(
472 true,
473 Value::Number(Number {
474 inner: NumberVariant::Unsigned(2)
475 }) == Value::Number(Number {
476 inner: NumberVariant::Signed(2)
477 })
478 );
479
480 assert_eq!(
481 true,
482 Value::Number(Number {
483 inner: NumberVariant::Unsigned(3)
484 }) > Value::Number(Number {
485 inner: NumberVariant::Signed(2)
486 })
487 );
488
489 assert_eq!(
490 true,
491 Value::Number(Number {
492 inner: NumberVariant::Unsigned(2)
493 }) < Value::Number(Number {
494 inner: NumberVariant::Signed(3)
495 })
496 );
497
498 assert_eq!(
500 true,
501 Value::Number(Number {
502 inner: NumberVariant::Signed(2)
503 }) == Value::Number(Number {
504 inner: NumberVariant::Unsigned(2)
505 })
506 );
507
508 assert_eq!(
509 true,
510 Value::Number(Number {
511 inner: NumberVariant::Signed(3)
512 }) > Value::Number(Number {
513 inner: NumberVariant::Unsigned(2)
514 })
515 );
516
517 assert_eq!(
518 true,
519 Value::Number(Number {
520 inner: NumberVariant::Signed(2)
521 }) < Value::Number(Number {
522 inner: NumberVariant::Unsigned(3)
523 })
524 );
525
526 assert_eq!(
528 true,
529 Value::Number(Number {
530 inner: NumberVariant::Signed(2)
531 }) == Value::Number(Number {
532 inner: NumberVariant::Float(2.0)
533 })
534 );
535
536 assert_eq!(
537 true,
538 Value::Number(Number {
539 inner: NumberVariant::Signed(3)
540 }) > Value::Number(Number {
541 inner: NumberVariant::Float(2.0)
542 })
543 );
544
545 assert_eq!(
546 true,
547 Value::Number(Number {
548 inner: NumberVariant::Signed(2)
549 }) < Value::Number(Number {
550 inner: NumberVariant::Float(3.0)
551 })
552 );
553
554 assert_eq!(
556 true,
557 Value::Number(Number {
558 inner: NumberVariant::Unsigned(2)
559 }) == Value::Number(Number {
560 inner: NumberVariant::Float(2.0)
561 })
562 );
563
564 assert_eq!(
565 true,
566 Value::Number(Number {
567 inner: NumberVariant::Unsigned(3)
568 }) > Value::Number(Number {
569 inner: NumberVariant::Float(2.0)
570 })
571 );
572
573 assert_eq!(
574 true,
575 Value::Number(Number {
576 inner: NumberVariant::Unsigned(2)
577 }) < Value::Number(Number {
578 inner: NumberVariant::Float(3.0)
579 })
580 );
581
582 Ok(())
583 }
584
585 #[test]
586 fn debug_tests() -> anyhow::Result<()> {
587 assert_eq!(format!("{:?}", Value::Null), "Null".to_string());
588
589 assert_eq!(
590 format!("{:?}", Value::String("Richard Woolsey".to_string())),
591 "String(\"Richard Woolsey\")".to_string()
592 );
593
594 assert_eq!(
595 format!(
596 "{:?}",
597 Value::List(vec![
598 Value::String("Aiden Ford".to_string()),
599 Value::String("Rodney McKay".to_string()),
600 Value::String("Ronon Dex".to_string())
601 ])
602 ),
603 "List [String(\"Aiden Ford\"), String(\"Rodney McKay\"), String(\"Ronon Dex\")]"
604 .to_string()
605 );
606
607 assert_eq!(
608 format!(
609 "{:?}",
610 Value::Number(Number {
611 inner: NumberVariant::Unsigned(2)
612 })
613 ),
614 "Number(2)".to_string()
615 );
616
617 assert_eq!(
618 format!(
619 "{:?}",
620 Value::Number(Number {
621 inner: NumberVariant::Signed(2)
622 })
623 ),
624 "Number(2)".to_string()
625 );
626
627 assert_eq!(
628 format!(
629 "{:?}",
630 Value::Number(Number {
631 inner: NumberVariant::Float(2.0)
632 })
633 ),
634 "Number(2)".to_string()
635 );
636
637 Ok(())
638 }
639}