1use std::fmt;
2
3#[derive(Debug, PartialEq, Clone)]
11pub enum Value {
12 Variable(String),
14 Int(i32),
16 Float(f64),
18 String(String),
20 Boolean(bool),
22 Null,
24 Enum(String),
26 List(Vec<Value>),
28 Object(Vec<(String, Value)>),
30}
31
32impl fmt::Display for Value {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Self::Variable(v) => write!(f, "${v}"),
36 Self::Int(i) => write!(f, "{i}"),
37 Self::Float(fl) => write!(f, "{fl}"),
38 Self::String(s) => {
39 if s.contains('"') | s.contains('\n') | s.contains('\r') {
40 write!(f, r#""""{s}""""#)
41 } else {
42 write!(f, r#""{s}""#)
43 }
44 }
45 Self::Boolean(b) => write!(f, "{b}"),
46 Self::Null => write!(f, "null"),
47 Self::Enum(val) => write!(f, "{val}"),
48 Self::List(list) => write!(
49 f,
50 "[{}]",
51 list.iter()
52 .map(|elt| format!("{elt}"))
53 .collect::<Vec<String>>()
54 .join(", ")
55 ),
56 Self::Object(obj) => write!(
57 f,
58 "{{ {} }}",
59 obj.iter()
60 .map(|(k, v)| format!("{}: {v}", String::from(k)))
61 .collect::<Vec<String>>()
62 .join(", ")
63 ),
64 }
65 }
66}
67
68macro_rules! to_number_value {
69 ($ty: path, $inner_type: path, $value_variant: ident) => {
70 impl From<$ty> for Value {
71 fn from(val: $ty) -> Self {
72 Self::$value_variant(val as $inner_type)
73 }
74 }
75 };
76 ($({$ty: path, $inner_type: path, $value_variant: ident}),+) => {
77 $(
78 to_number_value!($ty, $inner_type, $value_variant);
79 )+
80 };
81}
82
83to_number_value!(
85 {i64, i32, Int},
86 {i32, i32, Int},
87 {i16, i32, Int},
88 {i8, i32, Int},
89 {isize, i32, Int},
90 {u64, i32, Int},
91 {u32, i32, Int},
92 {u16, i32, Int},
93 {u8, i32, Int},
94 {usize, i32, Int},
95 {f64, f64, Float},
96 {f32, f64, Float}
97);
98
99impl From<String> for Value {
100 fn from(val: String) -> Self {
101 Self::String(val)
102 }
103}
104
105impl From<&str> for Value {
106 fn from(val: &str) -> Self {
107 Self::String(val.to_string())
108 }
109}
110
111impl From<bool> for Value {
112 fn from(val: bool) -> Self {
113 Self::Boolean(val)
114 }
115}