aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passwordmaker/base_conversion/iterative_conversion.rs19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/passwordmaker/base_conversion/iterative_conversion.rs b/src/passwordmaker/base_conversion/iterative_conversion.rs
index 438ef20..7d52e9b 100644
--- a/src/passwordmaker/base_conversion/iterative_conversion.rs
+++ b/src/passwordmaker/base_conversion/iterative_conversion.rs
@@ -17,6 +17,7 @@ pub(crate) struct IterativeBaseConversion<V,B>{
current_base_power : V,
remaining_digits : usize,
base : B,
+ switch_to_multiplication : bool, //count the number of divisions. After 1, current_value is smaller than max_base_power. After 2, it's safe to mutliply current_value by base.
}
impl<V,B> IterativeBaseConversion<V,B>
@@ -32,6 +33,7 @@ impl<V,B> IterativeBaseConversion<V,B>
current_base_power,
remaining_digits: highest_fitting_exponent + 1, //to the power of 0 is a digit too. Soo, if base^n is the largest fitting exponent, n+1 digits.
base,
+ switch_to_multiplication: false
}
}
@@ -59,7 +61,8 @@ impl<V,B> IterativeBaseConversion<V,B>
impl<V,B> std::iter::Iterator for IterativeBaseConversion<V,B>
where V : for<'a> DivAssign<&'a B> + //used between steps to go to next-lower current_base_power
RemAssignWithQuotient+ //used to get the result of each step.
- TryInto<B> //used to convert the result of each step. We _know_ this cannot fail, but requiring Into would be wrong.
+ TryInto<B>, //used to convert the result of each step. We _know_ this cannot fail, but requiring Into would be wrong.
+ for<'a> &'a V : Mul<&'a B, Output = Option<V>>
{
type Item = B;
@@ -69,7 +72,12 @@ impl<V,B> std::iter::Iterator for IterativeBaseConversion<V,B>
} else {
let result = self.current_value.rem_assign_with_quotient(&self.current_base_power);
- self.current_base_power /= &self.base;
+ if self.switch_to_multiplication {
+ self.current_value = (&self.current_value * &self.base).expect("Cannot overflow.");
+ } else {
+ self.current_base_power /= &self.base;
+ self.switch_to_multiplication = true;
+ }
self.remaining_digits = self.remaining_digits - 1;
//this cannot ever yield None.
@@ -171,4 +179,11 @@ mod iterative_conversion_tests{
// 3YPRS4FaC1KU
assert_eq!(i.skip_while(|x| *x == 0_u64).collect::<Vec<_>>(), vec![3, 34, 25, 27, 28, 4, 15, 36, 12, 1, 20, 30]);
}
+ #[test]
+ fn test_overflow_in_switch_to_multiplication(){
+ //This should simply not overflow ever.
+ let i = IterativeBaseConversion::new(MyU128(u128::MAX), 40);
+ let result = i.skip_while(|x| *x == 0_u64).collect::<Vec<_>>();
+ assert_eq!(result, vec![1, 8, 14, 11, 10, 3, 37, 5, 26, 17, 14, 0, 23, 37, 35, 24, 3, 11, 27, 20, 34, 18, 12, 6, 15]);
+ }
} \ No newline at end of file