1use crate::{Typ, ValArray, Value};
2use arcstr::literal;
3use compact_str::format_compact;
4use rust_decimal::Decimal;
5use std::{
6 cmp::{Ordering, PartialEq, PartialOrd},
7 hash::Hash,
8 iter, mem,
9 num::Wrapping,
10 ops::{Add, Div, Mul, Not, Rem, Sub},
11 panic::{catch_unwind, AssertUnwindSafe},
12};
13use triomphe::Arc;
14
15impl Hash for Value {
16 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
17 use std::num::FpCategory::*;
18 match self {
19 Value::U32(v) => {
20 0u8.hash(state);
21 v.hash(state)
22 }
23 Value::V32(v) => {
24 1u8.hash(state);
25 v.hash(state)
26 }
27 Value::I32(v) => {
28 2u8.hash(state);
29 v.hash(state)
30 }
31 Value::Z32(v) => {
32 3u8.hash(state);
33 v.hash(state)
34 }
35 Value::U64(v) => {
36 4u8.hash(state);
37 v.hash(state)
38 }
39 Value::V64(v) => {
40 5u8.hash(state);
41 v.hash(state)
42 }
43 Value::I64(v) => {
44 6u8.hash(state);
45 v.hash(state)
46 }
47 Value::Z64(v) => {
48 7u8.hash(state);
49 v.hash(state)
50 }
51 Value::F32(v) => {
52 8u8.hash(state);
53 let bits = v.to_bits();
54 match v.classify() {
55 Nan => ((bits & 0xFF00_0000) | 0x1).hash(state), _ => bits.hash(state),
57 }
58 }
59 Value::F64(v) => {
60 9u8.hash(state);
61 let bits = v.to_bits();
62 match v.classify() {
63 Nan => ((bits & 0xFFE0_0000_0000_0000) | 0x1).hash(state), _ => bits.hash(state),
65 }
66 }
67 Value::DateTime(d) => {
68 10u8.hash(state);
69 d.hash(state)
70 }
71 Value::Duration(d) => {
72 11u8.hash(state);
73 d.hash(state)
74 }
75 Value::String(c) => {
76 12u8.hash(state);
77 c.hash(state)
78 }
79 Value::Bytes(b) => {
80 13u8.hash(state);
81 b.hash(state)
82 }
83 Value::Bool(true) => 14u8.hash(state),
84 Value::Bool(false) => 15u8.hash(state),
85 Value::Null => 16u8.hash(state),
86 Value::Error(c) => match &**c {
87 Value::String(e) => {
88 18u8.hash(state);
89 e.hash(state)
90 }
91 v => {
92 21u8.hash(state);
93 v.hash(state)
94 }
95 },
96 Value::Array(a) => {
97 19u8.hash(state);
98 for v in a.iter() {
99 v.hash(state)
100 }
101 }
102 Value::Decimal(d) => {
103 20u8.hash(state);
104 d.hash(state);
105 }
106 Value::Map(m) => {
107 21u8.hash(state);
108 m.hash(state);
109 }
110 Value::U8(v) => {
111 22u8.hash(state);
112 v.hash(state)
113 }
114 Value::I8(v) => {
115 23u8.hash(state);
116 v.hash(state)
117 }
118 Value::U16(v) => {
119 24u8.hash(state);
120 v.hash(state)
121 }
122 Value::I16(v) => {
123 25u8.hash(state);
124 v.hash(state)
125 }
126 Value::Abstract(v) => {
127 26u8.hash(state);
128 v.hash(state)
129 }
130 }
131 }
132}
133
134impl PartialEq for Value {
135 fn eq(&self, rhs: &Value) -> bool {
136 use std::num::FpCategory::*;
137 Typ::get(self) == Typ::get(rhs)
138 && match (self, rhs) {
139 (Value::U8(l), Value::U8(r)) => l == r,
140 (Value::I8(l), Value::I8(r)) => l == r,
141 (Value::U16(l), Value::U16(r)) => l == r,
142 (Value::I16(l), Value::I16(r)) => l == r,
143 (Value::U32(l), Value::U32(r)) => l == r,
144 (Value::V32(l), Value::V32(r)) => l == r,
145 (Value::I32(l), Value::I32(r)) => l == r,
146 (Value::Z32(l), Value::Z32(r)) => l == r,
147 (Value::U64(l), Value::U64(r)) => l == r,
148 (Value::V64(l), Value::V64(r)) => l == r,
149 (Value::I64(l), Value::I64(r)) => l == r,
150 (Value::Z64(l), Value::Z64(r)) => l == r,
151 (Value::F32(l), Value::F32(r)) => match (l.classify(), r.classify()) {
152 (Nan, Nan) => true,
153 (_, _) => l == r,
154 },
155 (Value::F64(l), Value::F64(r)) => match (l.classify(), r.classify()) {
156 (Nan, Nan) => true,
157 (_, _) => l == r,
158 },
159 (Value::Decimal(l), Value::Decimal(r)) => l == r,
160 (Value::DateTime(l), Value::DateTime(r)) => l == r,
161 (Value::Duration(l), Value::Duration(r)) => l == r,
162 (Value::Bool(l), Value::Bool(r)) => l == r,
163 (Value::Null, Value::Null) => true,
164 (Value::String(l), Value::String(r)) => l == r,
165 (Value::Bytes(l), Value::Bytes(r)) => l == r,
166 (Value::Error(l), Value::Error(r)) => l == r,
167 (Value::Array(l), Value::Array(r)) => l == r,
168 (Value::Map(l), Value::Map(r)) => l == r,
169 (Value::Abstract(l), Value::Abstract(r)) => l == r,
170 (_, _) => false,
171 }
172 }
173}
174
175impl Eq for Value {}
176
177impl PartialOrd for Value {
178 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
179 use std::num::FpCategory::*;
180 match Typ::get(self).cmp(&Typ::get(other)) {
181 Ordering::Greater => Some(Ordering::Greater),
182 Ordering::Less => Some(Ordering::Less),
183 Ordering::Equal => match (self, other) {
184 (Value::U8(l), Value::U8(r)) => l.partial_cmp(r),
185 (Value::I8(l), Value::I8(r)) => l.partial_cmp(r),
186 (Value::U16(l), Value::U16(r)) => l.partial_cmp(r),
187 (Value::I16(l), Value::I16(r)) => l.partial_cmp(r),
188 (Value::U32(l), Value::U32(r)) => l.partial_cmp(r),
189 (Value::V32(l), Value::V32(r)) => l.partial_cmp(r),
190 (Value::I32(l), Value::I32(r)) => l.partial_cmp(r),
191 (Value::Z32(l), Value::Z32(r)) => l.partial_cmp(r),
192 (Value::U64(l), Value::U64(r)) => l.partial_cmp(r),
193 (Value::V64(l), Value::V64(r)) => l.partial_cmp(r),
194 (Value::I64(l), Value::I64(r)) => l.partial_cmp(r),
195 (Value::Z64(l), Value::Z64(r)) => l.partial_cmp(r),
196 (Value::F32(l), Value::F32(r)) => match (l.classify(), r.classify()) {
197 (Nan, Nan) => Some(Ordering::Equal),
198 (Nan, _) => Some(Ordering::Less),
199 (_, Nan) => Some(Ordering::Greater),
200 (_, _) => l.partial_cmp(r),
201 },
202 (Value::F64(l), Value::F64(r)) => match (l.classify(), r.classify()) {
203 (Nan, Nan) => Some(Ordering::Equal),
204 (Nan, _) => Some(Ordering::Less),
205 (_, Nan) => Some(Ordering::Greater),
206 (_, _) => l.partial_cmp(r),
207 },
208 (Value::Decimal(l), Value::Decimal(r)) => l.partial_cmp(r),
209 (Value::DateTime(l), Value::DateTime(r)) => l.partial_cmp(r),
210 (Value::Duration(l), Value::Duration(r)) => l.partial_cmp(r),
211 (Value::Bool(l), Value::Bool(r)) => l.partial_cmp(r),
212 (Value::Null, Value::Null) => Some(Ordering::Equal),
213 (Value::String(l), Value::String(r)) => l.partial_cmp(r),
214 (Value::Bytes(l), Value::Bytes(r)) => l.partial_cmp(r),
215 (Value::Error(l), Value::Error(r)) => l.partial_cmp(r),
216 (Value::Array(l), Value::Array(r)) => l.partial_cmp(r),
217 (Value::Map(l), Value::Map(r)) => l.partial_cmp(r),
218 (Value::Abstract(l), Value::Abstract(r)) => l.partial_cmp(r),
219 (_, _) => unreachable!(),
220 },
221 }
222 }
223}
224
225impl Ord for Value {
226 fn cmp(&self, other: &Self) -> Ordering {
227 self.partial_cmp(other).unwrap()
228 }
229}
230
231macro_rules! apply_op_mixed_int {
232 ($lhs:expr, $rhs:expr, $lhc:ident, $lht:ty, $op:tt) => {
233 match $rhs {
234 Value::U8(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
235 Value::I8(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
236 Value::U16(r) if mem::size_of::<u16>() > mem::size_of::<$lht>() => Value::U16((Wrapping($lhs as u16) $op Wrapping(r)).0),
237 Value::U16(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
238 Value::I16(r) if mem::size_of::<i16>() > mem::size_of::<$lht>() => Value::I16((Wrapping($lhs as i16) $op Wrapping(r)).0),
239 Value::I16(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
240 Value::U32(r) | Value::V32(r) if mem::size_of::<u32>() > mem::size_of::<$lht>() => Value::U32((Wrapping($lhs as u32) $op Wrapping(r)).0),
241 Value::U32(r) | Value::V32(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
242 Value::I32(r) | Value::Z32(r) if mem::size_of::<i32>() > mem::size_of::<$lht>() => Value::I32((Wrapping($lhs as i32) $op Wrapping(r)).0),
243 Value::I32(r) | Value::Z32(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
244 Value::U64(r) | Value::V64(r) if mem::size_of::<u64>() > mem::size_of::<$lht>() => Value::U64((Wrapping($lhs as u64) $op Wrapping(r)).0),
245 Value::U64(r) | Value::V64(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
246 Value::I64(r) | Value::Z64(r) if mem::size_of::<i64>() > mem::size_of::<$lht>() => Value::I64((Wrapping($lhs as i64) $op Wrapping(r)).0),
247 Value::I64(r) | Value::Z64(r) => Value::$lhc((Wrapping($lhs) $op Wrapping(r as $lht)).0),
248 Value::F32(r) => Value::F32(($lhs as f32) $op r),
249 Value::F64(r) => Value::F64(($lhs as f64) $op r),
250 Value::Decimal(r) => Value::Decimal(Arc::new(Decimal::from($lhs) $op *r)),
251 _ => unreachable!(),
252 }
253 }
254}
255
256macro_rules! apply_op_mixed_float {
257 ($lhs:expr, $rhs:expr, $lhc:ident, $lht:ty, $op:tt) => {
258 match $rhs {
259 Value::U8(r) => Value::$lhc($lhs $op r as $lht),
260 Value::I8(r) => Value::$lhc($lhs $op r as $lht),
261 Value::U16(r) => Value::$lhc($lhs $op r as $lht),
262 Value::I16(r) => Value::$lhc($lhs $op r as $lht),
263 Value::U32(r) | Value::V32(r) => Value::$lhc($lhs $op r as $lht),
264 Value::I32(r) | Value::Z32(r) => Value::$lhc($lhs $op r as $lht),
265 Value::U64(r) | Value::V64(r) => Value::$lhc($lhs $op r as $lht),
266 Value::I64(r) | Value::Z64(r) => Value::$lhc($lhs $op r as $lht),
267 Value::F32(r) => Value::$lhc($lhs $op r as $lht),
268 Value::F64(r) => Value::$lhc($lhs $op r as $lht),
269 Value::Decimal(r) => {
270 let d = match Decimal::try_from($lhs) {
271 Err(e) => return Value::error(format!("could not convert {e:?} to decimal")),
272 Ok(d) => d
273 };
274 Value::Decimal(Arc::new(d $op *r))
275 },
276 _ => unreachable!(),
277 }
278 }
279}
280
281macro_rules! apply_op_mixed_decimal {
282 ($lhs:expr, $rhs:expr, $op:tt) => {
283 match $rhs {
284 Value::U8(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
285 Value::I8(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
286 Value::U16(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
287 Value::I16(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
288 Value::U32(r) | Value::V32(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
289 Value::I32(r) | Value::Z32(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
290 Value::U64(r) | Value::V64(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
291 Value::I64(r) | Value::Z64(r) => Value::Decimal(Arc::new($lhs $op Decimal::from(r))),
292 Value::F32(r) => {
293 let d = match Decimal::try_from(r) {
294 Err(e) => return Value::error(format!("could not convert {e:?} to decimal")),
295 Ok(d) => d
296 };
297 Value::Decimal(Arc::new($lhs $op d))
298 },
299 Value::F64(r) => {
300 let d = match Decimal::try_from(r) {
301 Err(e) => return Value::error(format!("could not convert {e:?} to decimal")),
302 Ok(d) => d
303 };
304 Value::Decimal(Arc::new($lhs $op d))
305 }
306 _ => unreachable!(),
307 }
308 }
309}
310
311macro_rules! number {
312 () => {
313 Value::U8(_)
314 | Value::I8(_)
315 | Value::U16(_)
316 | Value::I16(_)
317 | Value::U32(_)
318 | Value::V32(_)
319 | Value::I32(_)
320 | Value::Z32(_)
321 | Value::U64(_)
322 | Value::V64(_)
323 | Value::I64(_)
324 | Value::Z64(_)
325 | Value::F32(_)
326 | Value::F64(_)
327 | Value::Decimal(_)
328 };
329}
330
331macro_rules! apply_op {
332 ($self:expr, $rhs:expr, $id:expr, $op:tt, $($pat:pat => $blk:block),+) => {
333 #[allow(unreachable_patterns)]
334 match ($self, $rhs) {
335 (Value::U8(l), Value::U8(r)) => Value::U8((Wrapping(l) $op Wrapping(r)).0),
336 (Value::I8(l), Value::I8(r)) => Value::I8((Wrapping(l) $op Wrapping(r)).0),
337 (Value::U16(l), Value::U16(r)) => Value::U16((Wrapping(l) $op Wrapping(r)).0),
338 (Value::I16(l), Value::I16(r)) => Value::I16((Wrapping(l) $op Wrapping(r)).0),
339 (Value::U32(l) | Value::V32(l), Value::U32(r) | Value::V32(r)) => {
340 Value::U32((Wrapping(l) $op Wrapping(r)).0)
341 }
342 (Value::I32(l) | Value::Z32(l), Value::I32(r) | Value::Z32(r)) => {
343 Value::I32((Wrapping(l) $op Wrapping(r)).0)
344 }
345 (Value::U64(l) | Value::V64(l), Value::U64(r) | Value::V64(r)) => {
346 Value::U64((Wrapping(l) $op Wrapping(r)).0)
347 }
348 (Value::I64(l) | Value::Z64(l), Value::I64(r) | Value::Z64(r)) => {
349 Value::I64((Wrapping(l) $op Wrapping(r)).0)
350 }
351 (Value::F32(l), Value::F32(r)) => Value::F32(l $op r),
352 (Value::F64(l), Value::F64(r)) => Value::F64(l $op r),
353 (Value::Decimal(l), Value::Decimal(r)) => Value::Decimal(Arc::new((*l) $op (*r))),
354 (Value::U8(l), v@ number!()) => apply_op_mixed_int!(l, v, U8, u8, $op),
355 (Value::I8(l), v@ number!()) => apply_op_mixed_int!(l, v, I8, i8, $op),
356 (Value::U16(l), v@ number!()) => apply_op_mixed_int!(l, v, U16, u16, $op),
357 (Value::I16(l), v@ number!()) => apply_op_mixed_int!(l, v, I16, i16, $op),
358 (Value::U32(l) | Value::V32(l), v@ number!()) => apply_op_mixed_int!(l, v, U32, u32, $op),
359 (Value::I32(l) | Value::Z32(l), v@ number!()) => apply_op_mixed_int!(l, v, I32, i32, $op),
360 (Value::U64(l) | Value::V64(l), v@ number!()) => apply_op_mixed_int!(l, v, U64, u64, $op),
361 (Value::I64(l) | Value::Z64(l), v@ number!()) => apply_op_mixed_int!(l, v, I64, i64, $op),
362 (Value::F32(l), v@ number!()) => apply_op_mixed_float!(l, v, F32, f32, $op),
363 (Value::F64(l), v@ number!()) => apply_op_mixed_float!(l, v, F64, f64, $op),
364 (Value::Decimal(l), v@ number!()) => apply_op_mixed_decimal!(*l, v, $op),
365 (Value::String(s), n) => match s.parse::<Value>() {
366 Err(e) => Value::error(format_compact!("{}", e).as_str()),
367 Ok(s) => s $op n,
368 }
369 (n, Value::String(s)) => match s.parse::<Value>() {
370 Err(e) => Value::error(format_compact!("{}", e).as_str()),
371 Ok(s) => n $op s,
372 },
373 (Value::Array(e0), Value::Array(e1)) => {
374 let (e0, e1) = if e0.len() < e1.len() { (e0, e1) } else { (e1, e0) };
375 let iter = e0
376 .iter()
377 .cloned()
378 .chain(iter::repeat(Value::F64($id)))
379 .zip(e1.iter().cloned());
380 Value::Array(iter.map(|(v0, v1)| v0 $op v1).collect())
381 }
382 (l @ Value::Array(_), n) => {
383 match n.cast(Typ::Array) {
384 None => Value::error(literal!("can't add to array")),
385 Some(r) => l $op r,
386 }
387 }
388 (n, r @ Value::Array(_)) => {
389 match n.cast(Typ::Array) {
390 None => Value::error(literal!("can't add to array")),
391 Some(l) => l $op r,
392 }
393 }
394 (Value::Map(_), _) | (_, Value::Map(_)) => Value::error(literal!("can't apply to Map")),
395 (Value::Bytes(_), _) | (_, Value::Bytes(_)) => {
396 Value::error(literal!("can't add bytes"))
397 }
398 (Value::Null, _) | (_, Value::Null) => {
399 Value::error(literal!("can't add null"))
400 }
401 | (Value::Error(_), _)
402 | (_, Value::Error(_)) => Value::error(literal!("can't add error types")),
403 (Value::Abstract(_), _) | (_, Value::Abstract(_)) => Value::error(literal!("can't add abstract types")),
404 (Value::Bool(true), n) => Value::U32(1) $op n,
405 (n, Value::Bool(true)) => n $op Value::U32(1),
406 (Value::Bool(false), n) => Value::U32(0) $op n,
407 (n, Value::Bool(false)) => n $op Value::U32(0),
408 $($pat => $blk),+
409 }
410 }
411}
412
413macro_rules! handle_arith_result {
414 ($res:ident, $fallback:literal) => {
415 match $res {
416 Ok(r) => r,
417 Err(e) => match e.downcast_ref::<String>() {
418 Some(s) => Value::error(s),
419 None => match e.downcast_ref::<&str>() {
420 Some(s) => Value::error(*s),
421 None => Value::error(literal!($fallback)),
422 },
423 },
424 }
425 };
426}
427
428impl Add for Value {
429 type Output = Value;
430
431 fn add(self, rhs: Self) -> Self {
432 let res = catch_unwind(AssertUnwindSafe(|| {
433 apply_op!(
434 self, rhs, 0., +,
435 (Value::DateTime(dt), Value::Duration(d))
436 | (Value::Duration(d), Value::DateTime(dt)) => {
437 match chrono::Duration::from_std(*d) {
438 Ok(d) => Value::DateTime(Arc::new((*dt) + d)),
439 Err(e) => Value::error(format_compact!("{}", e).as_str()),
440 }
441 },
442 (Value::Duration(d0), Value::Duration(d1)) => { Value::Duration(Arc::new((*d0) + (*d1))) },
443 (Value::Duration(_), _)
444 | (_, Value::Duration(_))
445 | (_, Value::DateTime(_))
446 | (Value::DateTime(_), _) => {
447 Value::error(literal!("can't add to datetime/duration"))
448 }
449 )
450 }));
451 handle_arith_result!(res, "panic while executing add")
452 }
453}
454
455impl Sub for Value {
456 type Output = Value;
457
458 fn sub(self, rhs: Self) -> Self {
459 let res = catch_unwind(AssertUnwindSafe(|| {
460 apply_op!(
461 self, rhs, 0., -,
462 (Value::DateTime(dt), Value::Duration(d))
463 | (Value::Duration(d), Value::DateTime(dt)) => {
464 match chrono::Duration::from_std(*d) {
465 Ok(d) => Value::DateTime(Arc::new((*dt) - d)),
466 Err(e) => Value::error(format_compact!("{}", e).as_str()),
467 }
468 },
469 (Value::Duration(d0), Value::Duration(d1)) => { Value::Duration(Arc::new((*d0) - (*d1))) },
470 (Value::Duration(_), _)
471 | (_, Value::Duration(_))
472 | (_, Value::DateTime(_))
473 | (Value::DateTime(_), _) => {
474 Value::error(literal!("can't sub datetime/duration"))
475 }
476 )
477 }));
478 handle_arith_result!(res, "panic while executing sub")
479 }
480}
481
482impl Mul for Value {
483 type Output = Value;
484
485 fn mul(self, rhs: Self) -> Self {
486 let res = catch_unwind(AssertUnwindSafe(|| {
487 apply_op!(
488 self, rhs, 1., *,
489 (Value::Duration(d), Value::U32(n) | Value::V32(n))
490 | (Value::U32(n) | Value::V32(n), Value::Duration(d)) => { Value::Duration(Arc::new((*d) * n)) },
491 (Value::Duration(d), Value::I32(n) | Value::Z32(n))
492 | (Value::I32(n) | Value::Z32(n), Value::Duration(d)) => {
493 if n < 0 { panic!("can't multiply a duration by a negative number") }
494 Value::Duration(Arc::new((*d) * n as u32))
495 },
496 (Value::Duration(d), Value::U64(n) | Value::V64(n))
497 | (Value::U64(n) | Value::V64(n), Value::Duration(d)) => {
498 Value::Duration(Arc::new((*d) * n as u32))
499 },
500 (Value::Duration(d), Value::I64(n) | Value::Z64(n))
501 | (Value::I64(n) | Value::Z64(n), Value::Duration(d)) => {
502 if n < 0 { panic!("can't multiply a duration by a negative number") }
503 Value::Duration(Arc::new((*d) * n as u32))
504 },
505 (Value::Duration(d), Value::F32(s)) | (Value::F32(s), Value::Duration(d)) => {
506 Value::Duration(Arc::new(d.mul_f32(s)))
507 },
508 (Value::Duration(d), Value::F64(s)) | (Value::F64(s), Value::Duration(d)) => {
509 Value::Duration(Arc::new(d.mul_f64(s)))
510 },
511 | (Value::Duration(_), _)
512 | (_, Value::Duration(_))
513 | (_, Value::DateTime(_))
514 | (Value::DateTime(_), _) => {
515 Value::error(literal!("can't mul datetime/duration"))
516 }
517 )
518 }));
519 handle_arith_result!(res, "panic while executing mul")
520 }
521}
522
523impl Div for Value {
524 type Output = Value;
525
526 fn div(self, rhs: Self) -> Self {
527 let res = catch_unwind(AssertUnwindSafe(|| {
528 apply_op!(
529 self, rhs, 1., /,
530 (Value::Duration(d), Value::U32(s) | Value::V32(s)) => { Value::Duration(Arc::new((*d) / s)) },
531 (Value::Duration(d), Value::I32(s) | Value::Z32(s)) => {
532 if s < 0 { panic!("can't divide duration by a negative number") }
533 Value::Duration(Arc::new((*d) / s as u32))
534 },
535 (Value::Duration(d), Value::U64(s) | Value::V64(s)) => {
536 Value::Duration(Arc::new((*d) / s as u32))
537 },
538 (Value::Duration(d), Value::I64(s) | Value::Z64(s)) => {
539 if s < 0 { panic!("can't divide duration by a negative number") }
540 Value::Duration(Arc::new((*d) / s as u32))
541 },
542 (Value::Duration(d), Value::F32(s)) => { Value::Duration(Arc::new(d.div_f32(s))) },
543 (Value::Duration(d), Value::F64(s)) => { Value::Duration(Arc::new(d.div_f64(s))) },
544 (Value::Duration(_), _)
545 | (_, Value::Duration(_))
546 | (_, Value::DateTime(_))
547 | (Value::DateTime(_), _) => {
548 Value::error(literal!("can't div datetime/duration"))
549 }
550 )
551 }));
552 handle_arith_result!(res, "panic while executing div")
553 }
554}
555
556impl Rem for Value {
557 type Output = Value;
558
559 fn rem(self, rhs: Self) -> Self::Output {
560 let res = catch_unwind(AssertUnwindSafe(|| {
561 apply_op!(
562 self, rhs, 1., %,
563 (Value::Duration(_), _)
564 | (_, Value::Duration(_))
565 | (_, Value::DateTime(_))
566 | (Value::DateTime(_), _) => {
567 Value::error(literal!("can't mod datetime/duration"))
568 }
569 )
570 }));
571 handle_arith_result!(res, "panic while executing mod")
572 }
573}
574
575impl Not for Value {
576 type Output = Value;
577
578 fn not(self) -> Self {
579 match self {
580 Value::Bool(v) => Value::Bool(!v),
581 Value::Null => Value::Null,
582 Value::U8(v) => Value::U8(!v),
583 Value::I8(v) => Value::I8(!v),
584 Value::U16(v) => Value::U16(!v),
585 Value::I16(v) => Value::I16(!v),
586 Value::U32(v) => Value::U32(!v),
587 Value::V32(v) => Value::V32(!v),
588 Value::I32(v) => Value::I32(!v),
589 Value::Z32(v) => Value::Z32(!v),
590 Value::U64(v) => Value::U64(!v),
591 Value::V64(v) => Value::V64(!v),
592 Value::I64(v) => Value::I64(!v),
593 Value::Z64(v) => Value::Z64(!v),
594 Value::F32(_) => Value::error(literal!("can't apply not to F32")),
595 Value::F64(_) => Value::error(literal!("can't apply not to F64")),
596 Value::Decimal(_) => Value::error(literal!("can't apply not to Decimal")),
597 Value::DateTime(_) => Value::error(literal!("can't apply not to DateTime")),
598 Value::Duration(_) => Value::error(literal!("can't apply not to Duration")),
599 Value::String(_) => Value::error(literal!("can't apply not to String")),
600 Value::Bytes(_) => Value::error(literal!("can't apply not to Bytes")),
601 Value::Error(_) => Value::error(literal!("can't apply not to Error")),
602 Value::Map(_) => Value::error(literal!("can't apply not to Map")),
603 Value::Abstract(_) => Value::error(literal!("can't apply not to Abstract")),
604 Value::Array(elts) => {
605 Value::Array(ValArray::from_iter_exact(elts.iter().cloned().map(|v| !v)))
606 }
607 }
608 }
609}