sequential/
sequence.rs

1use crate::seq_num::SeqNum;
2use std::iter::Iterator;
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// A number generator that produces monotonously increasing integer numbers,
8/// starting from a configurable start-point.
9///
10/// Can be fast-forwarded to skip numbers, but cannot be wound back.
11///
12/// Passivates itself when the configured maximum value or the limit of the chosen type `T` is reached.
13/// A passivated instance does not produce values anymore.
14///
15/// Optionally (with feature `serde`) implements `serde::Serialize` and `serde::Deserialize`.
16///
17/// Works with all unsigned integers, from `u8` to `u128`.
18///
19/// ## Example:
20///
21/// ```rust
22/// use sequential::Sequence;
23/// {
24///     let mut sequence = Sequence::<u8>::new();
25///     assert_eq!(sequence.next(), Some(0_u8));
26///     assert_eq!(sequence.next(), Some(1_u8));
27///
28///     sequence.continue_after(5);
29///     assert_eq!(sequence.next(), Some(6));
30///
31///     sequence.continue_after(15);
32///     sequence.continue_after(7);
33///     sequence.continue_after(0);
34///     assert_eq!(sequence.next(), Some(16));
35///     assert_eq!(sequence.peek(), Some(17));
36///     assert_eq!(sequence.peek(), Some(17));
37///     assert_eq!(sequence.next(), Some(17));
38/// }
39///
40/// {
41///     let mut sequence = Sequence::<u64>::new();
42///     sequence.continue_after(u64::MAX-1);
43///     assert!(sequence.next().is_some());
44///     assert!(sequence.next().is_none());
45/// }
46/// ```
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(Clone, Default, Debug)]
49pub struct Sequence<T>
50where
51    T: SeqNum,
52{
53    next: T,
54    // if > 0: the increment; if == 0: the instance is passivated
55    incr: T,
56    #[cfg_attr(feature = "serde", serde(default = "SeqNum::max_val"))]
57    max: T,
58}
59
60impl<T> Sequence<T>
61where
62    T: SeqNum,
63{
64    /// Produces an instance that starts with 0 and increments by 1.
65    #[must_use]
66    pub fn new() -> Self {
67        Self {
68            next: T::zero(),
69            incr: T::one(),
70            max: T::max_val(),
71        }
72    }
73
74    // Produces a dead instance, good for nothing.
75    #[must_use]
76    fn dead() -> Self {
77        Self {
78            next: T::zero(),
79            incr: T::zero(),
80            max: T::max_val(),
81        }
82    }
83
84    /// Produces an instance that starts with `val` and increments by 1.
85    #[must_use]
86    pub fn start_with(val: T) -> Self {
87        Self {
88            next: val,
89            incr: T::one(),
90            max: T::max_val(),
91        }
92    }
93
94    /// Produces an instance that starts with `val + 1` and increments by 1.
95    #[must_use]
96    pub fn start_after(val: T) -> Self {
97        match val.checked_add(T::one()) {
98            Some(next) => Self {
99                next,
100                incr: T::one(),
101                max: T::max_val(),
102            },
103            None => Self::dead(),
104        }
105    }
106
107    /// Produces an instance that starts after the highest value returned by the iterator.
108    pub fn start_after_highest(values: &mut dyn Iterator<Item = &T>) -> Self {
109        Self::start_after(
110            *values
111                .reduce(|x, y| std::cmp::max(x, y))
112                .unwrap_or(&T::zero()),
113        )
114    }
115
116    /// Produces an instance with explicitly configured upper limit.
117    pub fn with_start_end_increment(start: T, end: T, incr: T) -> Self {
118        Self {
119            next: start,
120            incr,
121            max: end,
122        }
123    }
124
125    /// Consumes the Sequence and produces one that increments with the given value.
126    ///
127    /// An increment of `0` produces a dead sequence that will not return any value.
128    ///
129    /// Note: the new increment takes effect _after_ the next value, not with the next value.
130    /// This is irrelevant if you call this method before consuming any value.
131    ///
132    /// ## Example
133    ///
134    /// ```rust
135    /// # use sequential::Sequence;
136    /// let mut sequence = Sequence::<usize>::new().with_increment(5);
137    /// assert_eq!(sequence.next(), Some(0));
138    /// assert_eq!(sequence.next(), Some(5));
139    /// assert_eq!(sequence.next(), Some(10));
140    /// ```
141    #[must_use]
142    pub fn with_increment(mut self, incr: T) -> Self {
143        if self.is_active() {
144            self.incr = incr;
145        }
146        self
147    }
148
149    /// Make sure that the Sequence will never produce the given value,
150    /// by increasing the next value if necessary.
151    pub fn continue_after(&mut self, val: T) {
152        match val.checked_add(self.incr) {
153            Some(candidate) => {
154                self.next = std::cmp::max(self.next, candidate);
155            }
156            None => {
157                self.set_passive();
158            }
159        }
160    }
161
162    /// Returns the value that will be returned by the next call to `next()`, but will not
163    /// advance the `Sequence`.
164    pub fn peek(&self) -> Option<T> {
165        if self.is_passive() {
166            None
167        } else {
168            Some(self.next)
169        }
170    }
171
172    fn set_passive(&mut self) {
173        self.incr = T::zero();
174    }
175    fn is_active(&self) -> bool {
176        self.incr != T::zero()
177    }
178    fn is_passive(&self) -> bool {
179        self.incr == T::zero()
180    }
181}
182
183/// Allows using Sequence for iterations.
184///
185/// Example
186///
187/// ```rust
188/// # use sequential::Sequence;
189/// assert_eq!(Sequence::<u8>::with_start_end_increment(23, 38, 3).sum::<u8>(),183);
190/// ```
191impl<T> Iterator for Sequence<T>
192where
193    T: SeqNum,
194{
195    type Item = T;
196
197    fn next(&mut self) -> Option<Self::Item> {
198        if self.is_passive() {
199            None
200        } else {
201            let current = self.next;
202            match self.next.checked_add(self.incr) {
203                Some(next) => {
204                    if next > self.max {
205                        self.set_passive();
206                    } else {
207                        self.next = next;
208                    }
209                }
210                None => {
211                    self.set_passive();
212                }
213            }
214            Some(current)
215        }
216    }
217}
218
219#[cfg(test)]
220mod test {
221    use super::Sequence;
222
223    #[test]
224    fn test_sequence() {
225        let mut sequence = Sequence::<usize>::new();
226        assert_eq!(sequence.next(), Some(0_usize));
227        assert_eq!(sequence.next(), Some(1_usize));
228
229        sequence.continue_after(5);
230        assert_eq!(sequence.next(), Some(6));
231
232        sequence.continue_after(15);
233        sequence.continue_after(7);
234        sequence.continue_after(0);
235        assert_eq!(sequence.next(), Some(16));
236        assert_eq!(sequence.peek(), Some(17));
237        assert_eq!(sequence.peek(), Some(17));
238        assert_eq!(sequence.next(), Some(17));
239    }
240
241    #[test]
242    fn test_increment() {
243        let mut sequence = Sequence::<u8>::new().with_increment(5);
244        assert_eq!(sequence.next(), Some(0));
245        assert_eq!(sequence.next(), Some(5));
246        assert_eq!(sequence.next(), Some(10));
247
248        sequence.continue_after(152);
249        assert_eq!(sequence.next(), Some(157));
250        assert_eq!(sequence.next(), Some(162));
251
252        sequence.continue_after(251);
253        assert_eq!(sequence.next(), None);
254    }
255
256    #[test]
257    fn test_exhaust() {
258        let mut sequence = Sequence::<u64>::new();
259        sequence.continue_after(u64::MAX - 2);
260        assert!(sequence.is_active());
261        assert!(sequence.next().is_some());
262
263        assert!(sequence.peek().is_some());
264        assert!(sequence.peek().is_some());
265        assert!(sequence.next().is_some());
266
267        assert!(sequence.peek().is_none());
268        assert!(sequence.next().is_none());
269    }
270
271    #[cfg(feature = "serde")]
272    #[test]
273    fn test_serde() {
274        let mut sequence = Sequence::<u32>::with_start_end_increment(22, 99, 11);
275        assert_eq!(sequence.next(), Some(22));
276        let s = serde_json::to_string(&sequence).unwrap();
277        assert_eq!(&*s, r#"{"next":33,"incr":11,"max":99}"#);
278
279        let mut sequence2: Sequence<u32> = serde_json::from_str(&*s).unwrap();
280        assert_eq!(sequence2.next(), Some(33));
281        assert_eq!(sequence2.next(), Some(44));
282        assert_eq!(sequence2.next(), Some(55));
283        assert_eq!(sequence2.next(), Some(66));
284        assert_eq!(sequence2.next(), Some(77));
285        assert_eq!(sequence2.next(), Some(88));
286        assert_eq!(sequence2.next(), Some(99));
287        assert_eq!(sequence2.next(), None);
288
289        // compatibility to old serialization format (without max)
290        let old_format = r#"{"next":88,"incr":11}"#;
291        let mut sequence3: Sequence<u32> = serde_json::from_str(&old_format).unwrap();
292        assert_eq!(sequence3.next(), Some(88));
293        assert_eq!(sequence3.next(), Some(99));
294        assert_eq!(sequence3.next(), Some(110));
295        assert_eq!(sequence3.next(), Some(121));
296    }
297
298    #[test]
299    fn test_iter() {
300        assert_eq!(
301            Sequence::<u8>::with_start_end_increment(23, 38, 3).sum::<u8>(),
302            183
303        );
304    }
305}