1use super::Substance;
6use crate::loader::Context;
7use crate::parsing::datetime;
8use crate::types::{DateTime, Number};
9use serde_derive::{Deserialize, Serialize};
10use std::ops::{Add, Div, Mul, Neg, Sub};
11
12#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq)]
13pub struct MissingDeps {
14 needed: Vec<String>,
15}
16
17impl MissingDeps {
18 pub fn new(name: &str) -> MissingDeps {
19 MissingDeps {
20 needed: vec![name.into()],
21 }
22 }
23
24 pub fn combine(left: &MissingDeps, right: &MissingDeps) -> MissingDeps {
25 MissingDeps {
26 needed: left
27 .needed
28 .iter()
29 .chain(right.needed.iter())
30 .cloned()
31 .collect(),
32 }
33 }
34
35 pub fn needed(&self) -> &[String] {
36 &self.needed
37 }
38}
39
40impl std::fmt::Display for MissingDeps {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(f, "missing {}", self.needed.join(", "))
43 }
44}
45
46#[derive(Clone, Debug)]
47pub enum Value {
48 Number(Number),
49 DateTime(DateTime),
50 Substance(Substance),
51 MissingDeps(MissingDeps),
52}
53
54pub trait Show {
55 fn show(&self, context: &Context) -> String;
57}
58
59impl Show for DateTime {
60 fn show(&self, context: &Context) -> String {
61 if let Some(h) = context.humanize(self) {
62 format!("{} ({})", self, h)
63 } else {
64 self.to_string()
65 }
66 }
67}
68
69impl Show for Value {
70 fn show(&self, context: &Context) -> String {
71 match *self {
72 Value::Number(ref num) => num.show(context),
73 Value::DateTime(ref dt) => dt.show(context),
74 Value::Substance(ref v) => v.show(context),
75 Value::MissingDeps(ref d) => format!("{d}"),
76 }
77 }
78}
79
80impl Value {
81 pub fn pow(&self, exp: &Value) -> Result<Value, String> {
82 match (self, exp) {
83 (&Value::Number(ref left), &Value::Number(ref right)) => {
84 left.pow(right).map(Value::Number)
85 }
86 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
87 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
88 }
89 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
90 Ok(Value::MissingDeps(a.clone()))
91 }
92 (_, _) => Err("Operation is not defined".to_string()),
93 }
94 }
95
96 pub fn as_number(&self) -> Option<&Number> {
97 if let Value::Number(ref num) = self {
98 Some(num)
99 } else {
100 None
101 }
102 }
103
104 pub fn to_number(&self) -> Option<Number> {
105 if let Value::Number(ref num) = self {
106 Some(num.clone())
107 } else {
108 None
109 }
110 }
111}
112
113impl<'a, 'b> Add<&'b Value> for &'a Value {
114 type Output = Result<Value, String>;
115
116 fn add(self, other: &Value) -> Result<Value, String> {
117 match (self, other) {
118 (&Value::Number(ref left), &Value::Number(ref right)) => (left + right)
119 .ok_or_else(|| {
120 "Addition of units with mismatched units is not meaningful".to_string()
121 })
122 .map(Value::Number),
123 (&Value::DateTime(ref left), &Value::Number(ref right))
124 | (&Value::Number(ref right), &Value::DateTime(ref left)) => left
125 .checked_add(datetime::to_duration(right)?)
126 .ok_or_else(|| {
127 "Implementation error: value is out of range representable by datetime"
128 .to_string()
129 })
130 .map(Value::DateTime),
131 (&Value::Substance(ref left), &Value::Substance(ref right)) => {
132 left.add(right).map(Value::Substance)
133 }
134 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
135 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
136 }
137 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
138 Ok(Value::MissingDeps(a.clone()))
139 }
140 (_, _) => Err("Operation is not defined".to_string()),
141 }
142 }
143}
144
145impl<'a, 'b> Sub<&'b Value> for &'a Value {
146 type Output = Result<Value, String>;
147
148 fn sub(self, other: &Value) -> Result<Value, String> {
149 match (self, other) {
150 (&Value::Number(ref left), &Value::Number(ref right)) => (left - right)
151 .ok_or_else(|| {
152 "Subtraction of units with mismatched units is not meaningful".to_string()
153 })
154 .map(Value::Number),
155 (&Value::DateTime(ref left), &Value::Number(ref right))
156 | (&Value::Number(ref right), &Value::DateTime(ref left)) => left
157 .checked_sub(datetime::to_duration(right)?)
158 .ok_or_else(|| {
159 "Implementation error: value is out of range representable by datetime"
160 .to_string()
161 })
162 .map(Value::DateTime),
163 (&Value::DateTime(ref left), &Value::DateTime(ref right)) => {
164 datetime::from_duration(&(left - right)).map(Value::Number)
165 }
166 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
167 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
168 }
169 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
170 Ok(Value::MissingDeps(a.clone()))
171 }
172 (_, _) => Err("Operation is not defined".to_string()),
173 }
174 }
175}
176
177impl<'a> Neg for &'a Value {
178 type Output = Result<Value, String>;
179
180 fn neg(self) -> Self::Output {
181 match *self {
182 Value::Number(ref num) => (-num)
183 .ok_or_else(|| "Bug: Negation should not fail".to_string())
184 .map(Value::Number),
185 Value::MissingDeps(ref d) => Ok(Value::MissingDeps(d.clone())),
186 _ => Err("Operation is not defined".to_string()),
187 }
188 }
189}
190
191impl<'a, 'b> Mul<&'b Value> for &'a Value {
192 type Output = Result<Value, String>;
193
194 fn mul(self, other: &Value) -> Result<Value, String> {
195 match (self, other) {
196 (&Value::Number(ref left), &Value::Number(ref right)) => (left * right)
197 .ok_or_else(|| "Bug: Mul should not fail".to_string())
198 .map(Value::Number),
199 (&Value::Number(ref co), &Value::Substance(ref sub))
200 | (&Value::Substance(ref sub), &Value::Number(ref co)) => {
201 (sub * co).map(Value::Substance)
202 }
203 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
204 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
205 }
206 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
207 Ok(Value::MissingDeps(a.clone()))
208 }
209 (_, _) => Err("Operation is not defined".to_string()),
210 }
211 }
212}
213
214impl<'a, 'b> Div<&'b Value> for &'a Value {
215 type Output = Result<Value, String>;
216
217 fn div(self, other: &Value) -> Result<Value, String> {
218 match (self, other) {
219 (&Value::Number(ref left), &Value::Number(ref right)) => (left / right)
220 .ok_or_else(|| "Division by zero".to_string())
221 .map(Value::Number),
222 (&Value::Substance(ref sub), &Value::Number(ref co)) => {
223 (sub / co).map(Value::Substance)
224 }
225 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
226 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
227 }
228 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
229 Ok(Value::MissingDeps(a.clone()))
230 }
231 (_, _) => Err("Operation is not defined".to_string()),
232 }
233 }
234}
235
236impl Value {
237 pub fn shl(&self, other: &Value) -> Result<Value, String> {
238 match (self, other) {
239 (&Value::Number(ref left), &Value::Number(ref right)) => {
240 left.shl(right).map(Value::Number)
241 }
242 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
243 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
244 }
245 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
246 Ok(Value::MissingDeps(a.clone()))
247 }
248 (_, _) => Err("Operation is not defined".to_string()),
249 }
250 }
251
252 pub fn shr(&self, other: &Value) -> Result<Value, String> {
253 match (self, other) {
254 (&Value::Number(ref left), &Value::Number(ref right)) => {
255 left.shr(right).map(Value::Number)
256 }
257 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
258 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
259 }
260 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
261 Ok(Value::MissingDeps(a.clone()))
262 }
263 (_, _) => Err("Operation is not defined".to_string()),
264 }
265 }
266
267 pub fn rem(&self, other: &Value) -> Result<Value, String> {
268 match (self, other) {
269 (&Value::Number(ref left), &Value::Number(ref right)) => {
270 left.rem(right).map(Value::Number)
271 }
272 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
273 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
274 }
275 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
276 Ok(Value::MissingDeps(a.clone()))
277 }
278 (_, _) => Err("Operation is not defined".to_string()),
279 }
280 }
281
282 pub fn and(&self, other: &Value) -> Result<Value, String> {
283 match (self, other) {
284 (&Value::Number(ref left), &Value::Number(ref right)) => {
285 left.and(right).map(Value::Number)
286 }
287 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
288 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
289 }
290 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
291 Ok(Value::MissingDeps(a.clone()))
292 }
293 (_, _) => Err("Operation is not defined".to_string()),
294 }
295 }
296
297 pub fn or(&self, other: &Value) -> Result<Value, String> {
298 match (self, other) {
299 (&Value::Number(ref left), &Value::Number(ref right)) => {
300 left.or(right).map(Value::Number)
301 }
302 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
303 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
304 }
305 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
306 Ok(Value::MissingDeps(a.clone()))
307 }
308 (_, _) => Err("Operation is not defined".to_string()),
309 }
310 }
311
312 pub fn xor(&self, other: &Value) -> Result<Value, String> {
313 match (self, other) {
314 (&Value::Number(ref left), &Value::Number(ref right)) => {
315 left.xor(right).map(Value::Number)
316 }
317 (&Value::MissingDeps(ref a), &Value::MissingDeps(ref b)) => {
318 Ok(Value::MissingDeps(MissingDeps::combine(a, b)))
319 }
320 (&Value::MissingDeps(ref a), _) | (_, &Value::MissingDeps(ref a)) => {
321 Ok(Value::MissingDeps(a.clone()))
322 }
323 (_, _) => Err("Operation is not defined".to_string()),
324 }
325 }
326}