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);