use std::cmp::max; use std::fmt::{Display, Formatter, Result as FormatResult}; use std::ops::Add; #[derive(Clone)] pub struct Number { pub integer_part: String, } macro_rules! int_conv { ($($t:ty),*) => {$( impl From<$t> for Number { fn from(x: $t) -> Number { Number { integer_part: x.to_string(), } } } )*}; } int_conv!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); impl Display for Number { fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult { f.write_str(&self.integer_part) } } impl Add for Number { type Output = Number; fn add(self, rhs: Self) -> Self::Output { let longest_ipart_len = max(self.integer_part.len(), rhs.integer_part.len()); let self_padded = format!("{:0>len$}", self.integer_part, len=longest_ipart_len); let rhs_padded = format!("{:0>len$}", rhs.integer_part, len=longest_ipart_len); let mut result_ipart_reverse = "".to_string(); let mut carry: u8 = 0; for (self_char, rhs_char) in self_padded.chars().rev().zip(rhs_padded.chars().rev()) { let self_char_val = self_char.to_digit(10).unwrap() as u8; let rhs_char_val = rhs_char.to_digit(10).unwrap() as u8; let sum = self_char_val + rhs_char_val + carry; let sum_last_digit = (sum % 10).to_string().chars().next().unwrap(); carry = sum / 10; result_ipart_reverse.push(sum_last_digit); } if carry > 0 { result_ipart_reverse.push_str(&carry.to_string()); } let result_ipart = result_ipart_reverse.chars().rev().collect(); Number { integer_part: result_ipart, } } }