use num_traits::Signed; use std::fmt::Display; use std::ops::{Add, AddAssign}; /// Wrapped signed integer with custom upper bound with wrapping of 0s to the upper bound #[derive(Eq, Clone, Copy)] pub struct CustomWrapped { pub val: T, pub bound: T, } impl Add for CustomWrapped { type Output = CustomWrapped; fn add(self, rhs: T) -> Self::Output { Self { val: ((self.val + rhs % self.bound) + self.bound) % self.bound, bound: self.bound, } } } impl Add for &CustomWrapped { type Output = CustomWrapped; fn add(self, rhs: T) -> Self::Output { CustomWrapped { val: ((self.val + rhs % self.bound) + self.bound) % self.bound, bound: self.bound, } } } impl AddAssign for CustomWrapped { fn add_assign(&mut self, rhs: T) { self.val = ((self.val + rhs % self.bound) + self.bound) % self.bound } } impl CustomWrapped { pub fn new(val: T, bound: T) -> Self { Self { val, bound } } } impl PartialEq for CustomWrapped { fn eq(&self, other: &Self) -> bool { self.val.eq(&other.val) } } impl PartialOrd for CustomWrapped { fn partial_cmp(&self, other: &Self) -> Option { self.val.partial_cmp(&other.val) } } impl Ord for CustomWrapped { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.val.cmp(&other.val) } } impl PartialEq for CustomWrapped { fn eq(&self, other: &T) -> bool { self.val == *other } } impl PartialOrd for CustomWrapped { fn partial_cmp(&self, other: &T) -> Option { self.val.partial_cmp(other) } } impl Display for CustomWrapped where T: Display, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.val.fmt(f) } } // impl Into for CustomWrapped { // fn into(self) -> T { // self.val // } // } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let result = add(2, 2); assert_eq!(result, 4); } }