aboutsummaryrefslogtreecommitdiff
path: root/src/passwordmaker/base_conversion/remainders.rs
diff options
context:
space:
mode:
authorAndreas Grois <andi@grois.info>2022-10-11 23:31:21 +0200
committerAndreas Grois <andi@grois.info>2022-10-11 23:31:21 +0200
commit3bfb55ece2f70fc9b1969a2ec9c55f7a00358b90 (patch)
tree52d952ef77eaaf23598f51d59bfbf1f1b559ca04 /src/passwordmaker/base_conversion/remainders.rs
parente5e3f40059239cba68d0ed8dd3c958545c80fbea (diff)
Refactor base_conversion. Fix hmac byte bug.
Moved the basis conversion into a submodule, to ease the upcoming rewrite. Add a couple of new integration tests. Fix a bug caused by misreading the PasswordMaker Pro HMAC code.
Diffstat (limited to 'src/passwordmaker/base_conversion/remainders.rs')
-rw-r--r--src/passwordmaker/base_conversion/remainders.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/passwordmaker/base_conversion/remainders.rs b/src/passwordmaker/base_conversion/remainders.rs
new file mode 100644
index 0000000..93570a1
--- /dev/null
+++ b/src/passwordmaker/base_conversion/remainders.rs
@@ -0,0 +1,74 @@
+/// Adds `calc_remainders(divisor)` method to types that have some implementation of the Division trait.
+pub(super) trait CalcRemainders<T, D>{
+ fn calc_remainders(self, divisor : D) -> Remainders<T,D>;
+}
+
+/// Implement `Division` to enable the `calc_remainders()` method for your type.
+pub(super) trait Division<D> where Self:Sized {
+ /// does in-place arbitrary-length division. Returns remainder.
+ fn divide(self, divisor : &D) -> DivisionResult<Self, D>;
+ fn is_zero(&self) -> bool;
+}
+
+/// Or mark your type as `UseGenericDivision` to just use `/` and `%` operators for types. Makes only sense for integers.
+pub(super) trait UseGenericDivision : Clone
+ + for <'a> std::ops::Div<&'a Self, Output = Self>
+ + for <'a> std::ops::Rem<&'a Self, Output = Self>
+ + Default
+ + Eq {}
+
+impl<T, D> CalcRemainders<T, D> for T
+ where T:Division<D>
+{
+ fn calc_remainders(self, divisor : D) -> Remainders<T, D> {
+ Remainders::new(self,divisor)
+ }
+}
+
+pub(super) struct Remainders<T, U>{
+ value : Option<T>,
+ divisor : U,
+}
+
+impl<U, T:Division<U>> Remainders<T, U> {
+ fn new(value : T, divisor : U) -> Self {
+ let value = if value.is_zero() { None } else { Some(value) };
+ Remainders {
+ value,
+ divisor,
+ }
+ }
+}
+
+impl<U, T:Division<U>> Iterator for Remainders<T,U>{
+ type Item=U;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(v) = self.value.take() {
+ let DivisionResult{result, remainder} = v.divide(&self.divisor);
+ self.value = if result.is_zero() { None } else { Some(result) };
+ Some(remainder)
+ } else {
+ None
+ }
+ }
+}
+
+pub(super) struct DivisionResult<T:Division<U>, U> {
+ pub result : T,
+ pub remainder : U,
+}
+
+impl<U> Division<U> for U
+ where U: UseGenericDivision
+{
+ fn divide(self, divisor : &Self) -> DivisionResult<Self, Self> {
+ DivisionResult {
+ result: self.clone().div(divisor),
+ remainder: self.rem(divisor)
+ }
+ }
+ fn is_zero(&self) -> bool {
+ *self == Self::default()
+ }
+} \ No newline at end of file