use num_traits::One;
use num_traits::ops::checked::CheckedAdd;
pub struct Fibonacci<T> {
curr: T,
next: Option<T>,
}
impl<T> Iterator for Fibonacci<T>
where
T: CheckedAdd + Copy,
{
type Item = T;
fn next(&mut self) -> Option<T> {
let curr = self.next?;
self.next = self.curr.checked_add(&curr);
self.curr = curr;
Some(self.curr)
}
}
pub fn fibonacci_iterator<T>() -> Fibonacci<T>
where
T: One + Copy,
{
let init = T::one();
Fibonacci {
curr: init,
next: Some(init),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sequence_is_correct() {
assert_eq!(
fibonacci_iterator::<u16>().take(16).collect::<Vec<_>>(),
vec![
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597
]
);
}
#[test]
fn u8_overflow() {
assert_eq!(
fibonacci_iterator::<u8>().collect::<Vec<_>>(),
vec![1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
);
}
}