netidx_value/
op.rs

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), // normalize NaN
56                    _ => 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), // normalize NaN
64                    _ => 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}