diff options
Diffstat (limited to 'src/eval/int.rs')
| -rw-r--r-- | src/eval/int.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/eval/int.rs b/src/eval/int.rs new file mode 100644 index 00000000..4e081617 --- /dev/null +++ b/src/eval/int.rs @@ -0,0 +1,81 @@ +use std::num::{NonZeroI64, NonZeroIsize, NonZeroU64, NonZeroUsize}; + +use super::{cast, Value}; + +macro_rules! signed_int { + ($($ty:ty)*) => { + $(cast! { + $ty, + self => Value::Int(self as i64), + v: i64 => v.try_into().map_err(|_| "number too large")?, + })* + } +} + +macro_rules! unsigned_int { + ($($ty:ty)*) => { + $(cast! { + $ty, + self => Value::Int(self as i64), + v: i64 => v.try_into().map_err(|_| { + if v < 0 { + "number must be at least zero" + } else { + "number too large" + } + })?, + })* + } +} + +macro_rules! signed_nonzero { + ($($ty:ty)*) => { + $(cast! { + $ty, + self => Value::Int(self.get() as i64), + v: i64 => v + .try_into() + .ok() + .and_then($ty::new) + .ok_or_else(|| if v == 0 { + "number must not be zero" + } else { + "number too large" + })?, + })* + } +} + +macro_rules! unsigned_nonzero { + ($($ty:ty)*) => { + $(cast! { + $ty, + self => Value::Int(self.get() as i64), + v: i64 => v + .try_into() + .ok() + .and_then($ty::new) + .ok_or_else(|| if v <= 0 { + "number must be positive" + } else { + "number too large" + })?, + })* + } +} + +signed_int! { + i8 i16 i32 isize +} + +unsigned_int! { + u8 u16 u32 u64 usize +} + +signed_nonzero! { + NonZeroI64 NonZeroIsize +} + +unsigned_nonzero! { + NonZeroU64 NonZeroUsize +} |
