/// Adds `calc_remainders(divisor)` method to types that have some implementation of the Division trait. pub(super) trait CalcRemainders{ fn calc_remainders(self, divisor : D) -> Remainders; } /// Implement `Division` to enable the `calc_remainders()` method for your type. pub(super) trait Division where Self:Sized { /// does in-place arbitrary-length division. Returns remainder. fn divide(self, divisor : &D) -> DivisionResult; 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 CalcRemainders for T where T:Division { fn calc_remainders(self, divisor : D) -> Remainders { Remainders::new(self,divisor) } } pub(super) struct Remainders{ value : Option, divisor : U, } impl> Remainders { fn new(value : T, divisor : U) -> Self { let value = if value.is_zero() { None } else { Some(value) }; Remainders { value, divisor, } } } impl> Iterator for Remainders{ type Item=U; fn next(&mut self) -> Option { 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, U> { pub result : T, pub remainder : U, } impl Division for U where U: UseGenericDivision { fn divide(self, divisor : &Self) -> DivisionResult { DivisionResult { result: self.clone().div(divisor), remainder: self.rem(divisor) } } fn is_zero(&self) -> bool { *self == Self::default() } }