1use std::ops::{AddAssign, MulAssign};
2
3// For implementing base10_digits() accessor on LitInt.
4pub(crate) struct BigInt {
5 digits: Vec<u8>,
6}
7
8impl BigInt {
9 pub(crate) fn new() -> Self {
10 BigInt { digits: Vec::new() }
11 }
12
13 pub(crate) fn to_string(&self) -> String {
14 let mut repr = String::with_capacity(self.digits.len());
15
16 let mut has_nonzero = false;
17 for digit in self.digits.iter().rev() {
18 has_nonzero |= *digit != 0;
19 if has_nonzero {
20 repr.push((*digit + b'0') as char);
21 }
22 }
23
24 if repr.is_empty() {
25 repr.push('0');
26 }
27
28 repr
29 }
30
31 fn reserve_two_digits(&mut self) {
32 let len = self.digits.len();
33 let desired =
34 len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize;
35 self.digits.resize(desired, 0);
36 }
37}
38
39impl AddAssign<u8> for BigInt {
40 // Assumes increment <16.
41 fn add_assign(&mut self, mut increment: u8) {
42 self.reserve_two_digits();
43
44 let mut i: usize = 0;
45 while increment > 0 {
46 let sum: u8 = self.digits[i] + increment;
47 self.digits[i] = sum % 10;
48 increment = sum / 10;
49 i += 1;
50 }
51 }
52}
53
54impl MulAssign<u8> for BigInt {
55 // Assumes base <=16.
56 fn mul_assign(&mut self, base: u8) {
57 self.reserve_two_digits();
58
59 let mut carry: u8 = 0;
60 for digit: &mut u8 in &mut self.digits {
61 let prod: u8 = *digit * base + carry;
62 *digit = prod % 10;
63 carry = prod / 10;
64 }
65 }
66}
67