From: Ian Jackson Date: Sun, 21 Feb 2021 16:09:45 +0000 (+0000) Subject: arithmetic checking: Provide new CheckedArith trait X-Git-Tag: otter-0.4.0~404 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=0821e8e9424af02a17319f554600d52c99786482;p=otter.git arithmetic checking: Provide new CheckedArith trait Nothing uses this yet so NFC. Signed-off-by: Ian Jackson --- diff --git a/src/utils.rs b/src/utils.rs index a5753a90..dc94e3c3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,6 +5,8 @@ use crate::imports::*; use crate::prelude::*; +use std::ops::Neg; + #[macro_export] macro_rules! ensure_eq { ($v1:expr, $v2:expr) => { @@ -176,6 +178,56 @@ impl Result> // todo: DerefMut +#[derive(Error,Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize)] +#[error("error parsing Z coordinate")] +pub struct FooParseError; + +#[derive(Error,Clone,Copy,Debug,Serialize,Deserialize)] +#[error("error parsing Z coordinate")] +pub struct CoordinateOverflow; + +pub trait CheckedArith: Copy + Clone + Debug + 'static { + fn checked_add(self, rhs: Self) -> Result; + fn checked_sub(self, rhs: Self) -> Result; + fn checked_mul(self, rhs: Self) -> Result; + fn checked_neg(self) -> Result; + fn checked_mulf(self, rhs: f64) -> Result; +} + +macro_rules! checked_inherent { {$n:ident($($formal:tt)*) $($actual:tt)*} => { + fn $n(self $($formal)*) -> Result { + self.$n($($actual)*).ok_or(CoordinateOverflow) + } +} } + +impl CheckedArith for i32 { + checked_inherent!{checked_add(, rhs: Self) rhs} + checked_inherent!{checked_sub(, rhs: Self) rhs} + checked_inherent!{checked_mul(, rhs: Self) rhs} + checked_inherent!{checked_neg( ) } + fn checked_mulf(self, rhs: f64) -> Result { + let lhs: f64 = self.into(); + let out: f64 = lhs.checked_mul(rhs)?; + let out: Self = num::NumCast::from(out).ok_or(CoordinateOverflow)?; + Ok(out) + } +} + +macro_rules! checked_float { {$n:ident($($formal:tt)*) $($modify:tt)*} => { + fn $n(self $($formal)*) -> Result { + let out = self $($modify)*; + if out.is_finite() { Ok(out) } else { Err(CoordinateOverflow) } + } +} } + +impl CheckedArith for f64 { + checked_float!{checked_add (, rhs: Self) + rhs } + checked_float!{checked_sub (, rhs: Self) - rhs } + checked_float!{checked_mul (, rhs: Self) * rhs } + checked_float!{checked_mulf(, rhs: Self) * rhs } + checked_float!{checked_neg() .neg()} +} + pub fn toml_merge<'u, S: 'u + AsRef, KV: IntoIterator