misfortunate/
comte.rs

1/// `Comte` claims to be an [ExactSizeIterator].
2/// At first Comte claims to be empty and if iterated returns None.
3/// However, Comte is not fused and after a `tap` it will subsequently give
4/// back cloned `rabbit`s forever.
5///
6/// Louis Apollinaire Christien Emmanuel Comte was a magician who may have performed the first hat-trick
7///
8/// # Examples
9///
10/// ```
11/// # use misfortunate::Comte;
12/// let mut hat = Comte::new("Rabbit");
13/// assert_eq!(hat.next(), None);
14/// assert_eq!(hat.next(), None);
15/// hat.tap();
16/// assert_eq!(hat.next(), Some("Rabbit"));
17/// assert_eq!(hat.next(), Some("Rabbit"));
18/// ```
19#[derive(Clone, Debug)]
20pub struct Comte<T> {
21    rabbit: T,
22    revealed: bool,
23}
24
25impl<T> Comte<T> {
26    /// Constructs a new `Comte` with a concealed `rabbit`
27    pub fn new(rabbit: T) -> Comte<T> {
28        Comte {
29            rabbit,
30            revealed: false,
31        }
32    }
33
34    /// Irreversible. Previously empty iterator now produces cloned `rabbit`s
35    pub fn tap(&mut self) {
36        self.revealed = true;
37    }
38}
39
40impl<T: Clone> Iterator for Comte<T> {
41    type Item = T;
42    fn next(&mut self) -> Option<T> {
43        if self.revealed {
44            Some(self.rabbit.clone())
45        } else {
46            None
47        }
48    }
49
50    fn size_hint(&self) -> (usize, Option<usize>) {
51        if self.revealed {
52            (usize::MAX, None)
53        } else {
54            (0, Some(0))
55        }
56    }
57}
58
59impl<T: Clone> ExactSizeIterator for Comte<T> {}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn create() {
67        let _ = Comte::new(42_u8);
68    }
69
70    #[test]
71    fn fused() {
72        let mut dud = Comte::new("Rabbit").fuse();
73        assert_eq!(dud.next(), None);
74        assert_eq!(dud.next(), None);
75        assert_eq!(dud.next(), None);
76    }
77
78    #[test]
79    fn sizes() {
80        let mut hat = Comte::new("Rabbit");
81        let (min, max) = hat.size_hint();
82        assert_eq!(min, 0);
83        assert_eq!(max, Some(0));
84        hat.tap();
85        let (min, max) = hat.size_hint();
86        assert_eq!(min, usize::MAX);
87        assert_eq!(max, None);
88    }
89
90    #[test]
91    fn length() {
92        let mut hat = Comte::new("Rabbit");
93        assert_eq!(hat.len(), 0);
94        assert_eq!(hat.next(), None);
95        assert_eq!(hat.next(), None);
96        assert_eq!(hat.next(), None);
97        hat.tap();
98        assert_eq!(hat.next(), Some("Rabbit"));
99    }
100
101    #[test]
102    #[should_panic]
103    fn length_panic() {
104        let mut hat = Comte::new("Rabbit");
105        assert_eq!(hat.len(), 0);
106        assert_eq!(hat.next(), None);
107        assert_eq!(hat.next(), None);
108        assert_eq!(hat.next(), None);
109        hat.tap();
110        assert_eq!(hat.next(), Some("Rabbit"));
111        assert_ne!(hat.len(), 0); // This panics because ExactSizeIterators shouldn't have infinite size
112    }
113}