safe_arithmetic/ops/
checked_add.rs1use crate::error::{Overflow, Underflow};
2use std::fmt::{self, Debug, Display};
3
4pub trait CheckedAdd<Rhs = Self>
5where
6 Self: Sized,
7{
8 type Output;
9 type Error;
10
11 fn checked_add(self, rhs: Rhs) -> Result<Self::Output, Self::Error>;
16}
17
18macro_rules! impl_unsigned_checked_add {
19 ( $T:ty ) => {
20 impl CheckedAdd for $T {
21 type Output = Self;
22 type Error = AddError<Self, Self>;
23
24 fn checked_add(self, rhs: Self) -> Result<Self::Output, Self::Error> {
25 num::CheckedAdd::checked_add(&self, &rhs)
26 .ok_or(rhs.overflows(self))
27 .map_err(AddError)
28 }
29 }
30 };
31}
32
33impl_unsigned_checked_add!(u32);
34
35macro_rules! impl_signed_checked_add {
36 ( $T:ty ) => {
37 impl CheckedAdd for $T {
38 type Output = Self;
39 type Error = AddError<Self, Self>;
40
41 fn checked_add(self, rhs: Self) -> Result<Self::Output, Self::Error> {
42 if rhs.is_negative() {
43 num::CheckedSub::checked_sub(&self, &rhs.abs())
44 .ok_or(rhs.underflows(self))
45 .map_err(AddError)
46 } else {
47 num::CheckedAdd::checked_add(&self, &rhs)
48 .ok_or(rhs.overflows(self))
49 .map_err(AddError)
50 }
51 }
52 }
53 };
54}
55
56impl_signed_checked_add!(i64);
57
58#[derive(PartialEq, Clone, Debug)]
59#[allow(clippy::module_name_repetitions)]
60pub struct AddError<Lhs, Rhs>(pub crate::error::Operation<Lhs, Rhs>);
61
62impl<Lhs, Rhs> crate::error::Arithmetic for AddError<Lhs, Rhs>
63where
64 Lhs: crate::Type,
65 Rhs: crate::Type,
66{
67}
68
69impl<Lhs, Rhs> std::error::Error for AddError<Lhs, Rhs>
70where
71 Lhs: Display + Debug,
72 Rhs: Display + Debug,
73{
74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75 self.0.cause.as_deref().map(crate::error::AsErr::as_err)
76 }
77}
78
79impl<Lhs, Rhs> Display for AddError<Lhs, Rhs>
80where
81 Lhs: Display,
82 Rhs: Display,
83{
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 match self.0.kind {
86 Some(kind) => write!(
87 f,
88 "adding {} to {} would {} {}",
89 self.0.rhs,
90 self.0.lhs,
91 kind,
92 std::any::type_name::<Lhs>(),
93 ),
94 None => write!(f, "cannot add {} to {}", self.0.rhs, self.0.lhs,),
95 }
96 }
97}