1use std::borrow::Borrow;
4
5use approx::{relative_eq, relative_ne};
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum Value {
10 Number(f32),
11 Bool(bool),
12 Text(String),
13 List(Vec<Value>),
14 None,
15}
16
17impl Value {
18 pub fn text(text: impl ToString) -> Value {
20 Value::Text(text.to_string())
21 }
22
23 pub fn is_none(&self) -> bool {
25 match self {
26 Self::None => true,
27 _ => false,
28 }
29 }
30
31 pub fn bool_or_false(&self) -> bool {
32 match self {
33 Self::Bool(b) => *b,
34 _ => false,
35 }
36 }
37
38 pub fn add(&self, other: &Self) -> Self {
40 if let Self::List(l1) = self {
41 let mut l1 = l1.clone();
42 if let Self::List(l2) = other {
43 let l2 = l2.clone();
44 l1.extend(l2);
45 } else {
46 l1.push(other.clone());
47 }
48 Self::List(l1)
49 } else if let Self::List(l2) = other {
50 let mut l2 = l2.clone();
51 l2.insert(0, self.clone());
52 Self::List(l2)
53 } else {
54 match self {
55 Self::Number(a) => match other {
56 Self::Number(b) => Self::Number(*a + *b),
57 Self::Bool(b) => Self::Number(*a + if *b { 1.0 } else { 0.0 }),
58 Self::Text(b) => Self::Text(format!("{a}{b}")),
59 Self::None => self.clone(),
60 _ => Self::None,
61 },
62 Self::Bool(a) => match other {
63 Self::Number(b) => Self::Number(if *a { 1.0 } else { 0.0 } + *b),
64 Self::Text(b) => {
65 Self::Text(format!("{}{b}", if *a { "true" } else { "false" }))
66 }
67 _ => Self::None,
68 },
69 Self::Text(a) => match other {
70 Self::Number(b) => Self::Text(format!("{a}{b}")),
71 Self::Bool(b) => {
72 Self::Text(format!("{a}{}", if *b { "true" } else { "false" }))
73 }
74 Self::Text(b) => Self::Text(format!("{a}{b}")),
75 Self::None => self.clone(),
76 _ => Self::None,
77 },
78 Self::None => other.clone(),
79 _ => Self::None,
80 }
81 }
82 }
83
84 pub fn sub(&self, other: &Self) -> Self {
85 match self {
86 Self::Number(a) => match other {
87 Self::Number(b) => Self::Number(*a - *b),
88 _ => Self::None,
89 },
90 _ => Self::None,
91 }
92 }
93
94 pub fn mul(&self, other: &Self) -> Self {
95 match self {
96 Self::Number(a) => match other {
97 Self::Number(b) => Self::Number(*a * *b),
98 _ => Self::None,
99 },
100 _ => Self::None,
101 }
102 }
103
104 pub fn div(&self, other: &Self) -> Self {
105 match self {
106 Self::Number(a) => match other {
107 Self::Number(b) => Self::Number(*a / *b),
108 _ => Self::None,
109 },
110 _ => Self::None,
111 }
112 }
113
114 pub fn neg(&self) -> Self {
115 match self {
116 Self::Number(a) => Self::Number(-*a),
117 _ => Self::None,
118 }
119 }
120
121 pub fn not(&self) -> Self {
123 match self {
124 Self::Bool(a) => Self::Bool(!*a),
125 _ => Self::None,
126 }
127 }
128
129 fn logic_helper(&self, other: &Self, op: impl Fn(bool, bool) -> bool) -> Value {
130 match self {
131 Self::Bool(a) => match other {
132 Self::Bool(b) => Self::Bool(op(*a, *b)),
133 _ => Self::None,
134 },
135 _ => Self::None,
136 }
137 }
138
139 pub fn or(&self, other: &Self) -> Self {
140 Self::logic_helper(&self, other, |a, b| a || b)
141 }
142
143 pub fn and(&self, other: &Self) -> Self {
144 Self::logic_helper(&self, other, |a, b| a && b)
145 }
146
147 fn compare_numbers(&self, other: &Self, op: impl Fn(f32, f32) -> bool) -> Value {
149 match self {
150 Self::Number(a) => match other {
151 Self::Number(b) => Self::Bool(op(*a, *b)),
152 _ => Self::None,
153 },
154 _ => Self::None,
155 }
156 }
157
158 pub fn less_than(&self, other: &Self) -> Self {
159 self.compare_numbers(other, |a, b| a < b)
160 }
161
162 pub fn less_equals(&self, other: &Self) -> Self {
163 self.compare_numbers(other, |a, b| a <= b)
164 }
165
166 pub fn greater_than(&self, other: &Self) -> Self {
167 self.compare_numbers(other, |a, b| a > b)
168 }
169
170 pub fn greater_equals(&self, other: &Self) -> Self {
171 self.compare_numbers(other, |a, b| a >= b)
172 }
173
174 pub fn equals(&self, other: &Self) -> Self {
175 if let (Self::Number(a), Self::Number(b)) = (self, other) {
176 return Self::Bool(relative_eq!(*a, *b));
177 }
178
179 if let (Self::Bool(a), Self::Bool(b)) = (self, other) {
180 return Self::Bool(a == b);
181 }
182
183 if let (Self::Text(a), Self::Text(b)) = (self, other) {
184 return Self::Bool(a == b);
185 }
186
187 if self.is_none() && other.is_none() {
188 return Self::Bool(true);
189 }
190
191 if self.is_none() || other.is_none() {
192 return Self::Bool(false);
193 }
194
195 Self::None
196 }
197
198 pub fn not_equals(&self, other: &Self) -> Self {
199 if let (Self::Number(a), Self::Number(b)) = (self, other) {
200 return Self::Bool(!relative_ne!(*a, *b));
201 }
202
203 if let (Self::Bool(a), Self::Bool(b)) = (self, other) {
204 return Self::Bool(a != b);
205 }
206
207 if let (Self::Text(a), Self::Text(b)) = (self, other) {
208 return Self::Bool(a != b);
209 }
210
211 if self.is_none() && other.is_none() {
212 return Self::Bool(false);
213 }
214
215 if self.is_none() || other.is_none() {
216 return Self::Bool(true);
217 }
218
219 Self::None
220 }
221}
222
223impl<B: Borrow<Value>> std::ops::Add<B> for &Value {
224 type Output = Value;
225
226 fn add(self, rhs: B) -> Self::Output {
227 Value::add(&self, rhs.borrow())
228 }
229}
230
231impl ToString for Value {
232 fn to_string(&self) -> String {
233 match self {
234 Self::Number(a) => a.to_string(),
235 Self::Bool(a) => a.to_string(),
236 Self::Text(a) => a.to_string(),
237 Self::List(l) => format!(
238 "[{}]",
239 l.iter()
240 .map(|v| v.to_string())
241 .collect::<Vec<_>>()
242 .join(", ")
243 ),
244 Self::None => String::new(),
245 }
246 }
247}