aboutsummaryrefslogtreecommitdiff
path: root/src/passwordmaker/remainders_impl.rs
diff options
context:
space:
mode:
authorAndreas Grois <andi@grois.info>2022-10-09 00:06:35 +0200
committerAndreas Grois <andi@grois.info>2022-10-09 00:06:35 +0200
commit5e51b706d54a26470f33d1342f4666d5aab921fc (patch)
tree97307b8419b6572dcffc2842ef1474b4aa89f397 /src/passwordmaker/remainders_impl.rs
Initial Commit: PasswordMaker itself.
It's compiling, and the public interface is semi-OK now. The internals are still a bit gory, but they'll likely see an iteartion later on anyhow.
Diffstat (limited to 'src/passwordmaker/remainders_impl.rs')
-rw-r--r--src/passwordmaker/remainders_impl.rs76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/passwordmaker/remainders_impl.rs b/src/passwordmaker/remainders_impl.rs
new file mode 100644
index 0000000..7de2189
--- /dev/null
+++ b/src/passwordmaker/remainders_impl.rs
@@ -0,0 +1,76 @@
+use super::remainders::{Division, UseGenericDivision, DivisionResult};
+
+impl UseGenericDivision for u128{} //for Md4, Md5
+
+impl<const N : usize> Division<usize> for [u32;N] {
+ #[allow(clippy::cast_possible_truncation)]
+ fn divide(mut self, divisor : &usize) -> DivisionResult<Self, usize> {
+ #[cfg(target_pointer_width = "64")]
+ type UsizeAndFour = u128;
+ #[cfg(not(target_pointer_width = "64"))]
+ type UsizeAndFour = u64;
+ assert!((UsizeAndFour::MAX >> 32) as u128 >= usize::MAX as u128);
+
+ //uses mutation, because why not? self is owned after all :D
+ let divisor : UsizeAndFour = *divisor as UsizeAndFour;
+ let remainder = self.iter_mut().fold(0 as UsizeAndFour,|carry, current| {
+ assert_eq!(carry, carry & (usize::MAX as UsizeAndFour)); //carry has to be lower than divisor, and divisor is usize.
+ let carry_shifted = carry << 32;
+ let dividend = (carry_shifted) + (*current as UsizeAndFour);
+ let ratio = dividend / divisor;
+ assert_eq!(ratio, ratio & 0xffff_ffff); //this is fine. The first digit after re-adding the carry is alwys zero.
+ *current = (ratio) as u32;
+ dividend - (*current as UsizeAndFour) * divisor
+ });
+ assert_eq!(remainder, remainder & (usize::MAX as UsizeAndFour));
+ let remainder = remainder as usize;
+ DivisionResult{
+ result: self,
+ remainder,
+ }
+ }
+
+ fn is_zero(&self) -> bool {
+ self.iter().all(|x| *x == 0)
+ }
+}
+
+#[cfg(test)]
+mod remainders_tests{
+ use super::super::remainders::CalcRemainders;
+
+ use super::*;
+ #[test]
+ fn test_generic_division(){
+ let v = 50u128;
+ let d = 7u128;
+ let DivisionResult{result, remainder}=v.divide(&d);
+ assert_eq!(7, result);
+ assert_eq!(1, remainder);
+ }
+
+ #[test]
+ fn test_remainders() {
+ //relies on generic division.
+ let v = 141u128;
+ let d = 3u128;
+ let results : Vec<u128> = v.calc_remainders(d).collect();
+ assert_eq!(results, vec![0u128,2u128,0u128,2u128,1u128])
+ }
+
+ #[test]
+ fn test_array_divide() {
+ let dividend_int = 0xe7f1ec3a5f35af805407a8a531eefb79u128;
+ let dividend = [(dividend_int >> 96) as u32, ((dividend_int >> 64) & 0xffffffff) as u32, ((dividend_int >> 32) & 0xffffffff) as u32, (dividend_int & 0xffffffff) as u32];
+ #[cfg(target_pointer_width = "64")]
+ let divisor = 1531534813576487;
+ #[cfg(not(target_pointer_width = "64"))]
+ let divisor = 1531534813;
+ let result_int = dividend_int / (divisor as u128);
+ let remainder_int = dividend_int % (divisor as u128);
+ let result = dividend.divide(&divisor);
+ assert_eq!(result.result, [(result_int >> 96) as u32, ((result_int >> 64) & 0xffffffff) as u32, ((result_int >> 32) & 0xffffffff) as u32, (result_int & 0xffffffff) as u32]);
+ assert_eq!(remainder_int, result.remainder as u128);
+ }
+
+} \ No newline at end of file