1use std::{mem, ops::RangeFrom};
36
37pub trait Perpetuity: Sized {
39 type Item;
40
41 fn next_item(&mut self) -> Self::Item;
42
43 fn into_iter(self) -> IntoIter<Self> {
44 IntoIter(self)
45 }
46
47 fn take(self, count: usize) -> Take<Self> {
48 Take { items: self, count }
49 }
50}
51
52pub fn assimilate<T>(items: impl Perpetuity<Item = T>) -> impl Perpetuity<Item = T> {
60 items
61}
62
63pub struct IntoIter<I: Perpetuity>(I);
64
65impl<I: Perpetuity> Iterator for IntoIter<I> {
66 type Item = I::Item;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 Some(self.0.next_item())
70 }
71
72 fn size_hint(&self) -> (usize, Option<usize>) {
73 (usize::MAX, None)
74 }
75}
76
77pub struct Take<I: Perpetuity> {
78 items: I,
79 count: usize,
80}
81
82impl<I: Perpetuity> Iterator for Take<I> {
83 type Item = I::Item;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 (self.count > 0).then(|| {
87 self.count -= 1;
88 self.items.next_item()
89 })
90 }
91}
92
93pub struct Successors<T, F: FnMut(&T) -> T> {
94 next: T,
95 succ: F,
96}
97
98impl<T, F: FnMut(&T) -> T> Perpetuity for Successors<T, F> {
99 type Item = T;
100 fn next_item(&mut self) -> Self::Item {
101 let next = (self.succ)(&self.next);
102 mem::replace(&mut self.next, next)
103 }
104}
105
106macro_rules! range_from {
107 ($t:ty) => {
108 impl Perpetuity for RangeFrom<$t> {
109 type Item = $t;
110 fn next_item(&mut self) -> Self::Item {
111 <Self as Iterator>::next(self).unwrap()
112 }
113 }
114 };
115}
116
117range_from!(i8);
118range_from!(i16);
119range_from!(i32);
120range_from!(i64);
121range_from!(i128);
122range_from!(u8);
123range_from!(u16);
124range_from!(u32);
125range_from!(u64);
126range_from!(u128);
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn next_item() {
134 let mut got = Vec::new();
135 let mut count = 0..;
136 for _ in 0..4 {
137 got.push(count.next_item());
138 }
139 assert_eq!(got, [0, 1, 2, 3]);
140 }
141
142 #[test]
143 fn into_iter() {
144 let got: Vec<i32> = assimilate(0..).into_iter().take(4).collect();
145 assert_eq!(got, [0, 1, 2, 3]);
146 }
147
148 #[test]
149 fn take() {
150 let got: Vec<i32> = assimilate(0..).take(4).collect();
151 assert_eq!(got, [0, 1, 2, 3]);
152 }
153}