litcheck_filecheck/expr/
value.rs1use std::{borrow::Cow, convert::Infallible, fmt, str::FromStr};
2
3use crate::expr::{Expr, NumberFormat};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum Value<'a> {
7 Undef,
8 Str(Cow<'a, str>),
9 Num(Expr),
10}
11
12impl fmt::Display for Value<'_> {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14 match self {
15 Self::Undef => Ok(()),
16 Self::Str(s) => f.write_str(s.as_ref()),
17 Self::Num(expr) => write!(f, "{expr}"),
18 }
19 }
20}
21
22impl FromStr for Value<'_> {
23 type Err = Infallible;
24
25 fn from_str(s: &str) -> Result<Self, Self::Err> {
26 if s.is_empty() {
27 Ok(Value::Str(Cow::Borrowed("")))
28 } else {
29 Ok(Value::Str(Cow::Owned(s.to_string())))
30 }
31 }
32}
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq)]
35pub enum ValueType {
36 String,
37 Number(Option<NumberFormat>),
38}
39
40impl fmt::Display for ValueType {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::String => f.write_str("string"),
44 Self::Number(None) => f.write_str("any number"),
45 Self::Number(Some(format)) => f.write_str(&format.describe()),
46 }
47 }
48}
49
50impl PartialOrd for ValueType {
51 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
52 Some(self.cmp(other))
53 }
54}
55
56impl Ord for ValueType {
57 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
58 use core::cmp::Ordering;
59 match (self, other) {
60 (Self::String, Self::String) => Ordering::Equal,
61 (Self::String, _) => Ordering::Less,
62 (_, Self::String) => Ordering::Greater,
63 (Self::Number(a), Self::Number(b)) => {
64 let a = a.unwrap_or_default();
65 let b = b.unwrap_or_default();
66 if a == b {
67 Ordering::Equal
68 } else {
69 let ap = a.precision();
70 let bp = b.precision();
71 if ap == 0 && bp > 0 {
72 Ordering::Greater
73 } else if ap > 0 && bp == 0 {
74 Ordering::Less
75 } else {
76 ap.cmp(&bp)
77 .then_with(|| a.discriminant().cmp(&b.discriminant()))
78 }
79 }
80 }
81 }
82 }
83}