moxcms/
safe_math.rs

1/*
2 * // Copyright (c) Radzivon Bartoshyk 3/2025. All rights reserved.
3 * //
4 * // Redistribution and use in source and binary forms, with or without modification,
5 * // are permitted provided that the following conditions are met:
6 * //
7 * // 1.  Redistributions of source code must retain the above copyright notice, this
8 * // list of conditions and the following disclaimer.
9 * //
10 * // 2.  Redistributions in binary form must reproduce the above copyright notice,
11 * // this list of conditions and the following disclaimer in the documentation
12 * // and/or other materials provided with the distribution.
13 * //
14 * // 3.  Neither the name of the copyright holder nor the names of its
15 * // contributors may be used to endorse or promote products derived from
16 * // this software without specific prior written permission.
17 * //
18 * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29use crate::CmsError;
30use std::ops::Add;
31
32pub(crate) trait SafeAdd<T: Copy + Add<T, Output = T>> {
33    fn safe_add(&self, other: T) -> Result<T, CmsError>;
34}
35
36pub(crate) trait SafeMul<T: Copy + Add<T, Output = T>> {
37    fn safe_mul(&self, other: T) -> Result<T, CmsError>;
38}
39
40pub(crate) trait SafePowi<T: Copy + Add<T, Output = T>> {
41    fn safe_powi(&self, power: u32) -> Result<T, CmsError>;
42}
43
44macro_rules! safe_add_impl {
45    ($type_name: ident) => {
46        impl SafeAdd<$type_name> for $type_name {
47            #[inline(always)]
48            fn safe_add(&self, other: $type_name) -> Result<$type_name, CmsError> {
49                if let Some(result) = self.checked_add(other) {
50                    return Ok(result);
51                }
52                Err(CmsError::OverflowingError)
53            }
54        }
55    };
56}
57
58safe_add_impl!(u16);
59safe_add_impl!(u32);
60safe_add_impl!(i32);
61safe_add_impl!(usize);
62safe_add_impl!(isize);
63
64macro_rules! safe_mul_impl {
65    ($type_name: ident) => {
66        impl SafeMul<$type_name> for $type_name {
67            #[inline(always)]
68            fn safe_mul(&self, other: $type_name) -> Result<$type_name, CmsError> {
69                if let Some(result) = self.checked_mul(other) {
70                    return Ok(result);
71                }
72                Err(CmsError::OverflowingError)
73            }
74        }
75    };
76}
77
78safe_mul_impl!(u16);
79safe_mul_impl!(u32);
80safe_mul_impl!(i32);
81safe_mul_impl!(usize);
82safe_mul_impl!(isize);
83
84macro_rules! safe_powi_impl {
85    ($type_name: ident) => {
86        impl SafePowi<$type_name> for $type_name {
87            #[inline(always)]
88            fn safe_powi(&self, power: u32) -> Result<$type_name, CmsError> {
89                if let Some(result) = self.checked_pow(power) {
90                    return Ok(result);
91                }
92                Err(CmsError::OverflowingError)
93            }
94        }
95    };
96}
97
98safe_powi_impl!(u8);
99safe_powi_impl!(u16);
100safe_powi_impl!(u32);
101safe_powi_impl!(i32);
102safe_powi_impl!(usize);
103safe_powi_impl!(isize);