bounce_iterator/
lib.rs

1use std::{rc::Rc, sync::RwLock};
2
3#[derive(Default)]
4pub enum BounceState {
5    Reverse,
6    #[default]
7    Forward,
8    NoBounce,
9}
10
11// TODO: when I have some caffeine, come up with a better name
12pub fn rwlockify<T: Clone>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = Rc<RwLock<T>>> {
13    iter.map(|x| Rc::new(RwLock::new(x.to_owned())))
14}
15
16// TODO: panic is rude
17pub fn unrwlockify<T: Clone>(iter: impl Iterator<Item = Rc<RwLock<T>>>) -> impl Iterator<Item = T> {
18    iter.map(|x| x.read().expect("Failed to read RWlock").to_owned())
19}
20
21pub struct BounceIterLockedMut<T> {
22    collection: Vec<Rc<RwLock<T>>>,
23    index: usize,
24    bounce_state: BounceState,
25}
26
27// TODO: builtin peekability
28// composibility on uniquely featured iterators is somewhat poor,
29// so we must implement this ourselves
30impl<T> BounceIterLockedMut<T> {
31    pub fn reset(&mut self) {
32        self.index = 0;
33    }
34    pub fn reset_rev(&mut self) {
35        self.index = self.collection.len() - 1;
36    }
37    pub fn new(collection: Vec<Rc<RwLock<T>>>) -> Self {
38        Self {
39            collection,
40            index: 0,
41            bounce_state: Default::default(),
42        }
43    }
44    pub fn new_rev(collection: Vec<Rc<RwLock<T>>>) -> Self {
45        let len = collection.len() - 1;
46        Self {
47            collection,
48            index: len,
49            bounce_state: Default::default(),
50        }
51    }
52}
53
54impl<T> Iterator for BounceIterLockedMut<T> {
55    type Item = Rc<RwLock<T>>;
56
57    fn next(&mut self) -> Option<Self::Item> {
58        let len = self.collection.len();
59        if len > 1 {
60            if self.index >= len {
61                self.bounce_state = BounceState::Reverse;
62                self.index = len - 2;
63            } else if self.index == 0 {
64                self.bounce_state = BounceState::Forward;
65            }
66        } else {
67            self.bounce_state = BounceState::NoBounce;
68        }
69        let ret = self.collection.get(self.index).cloned();
70
71        match self.bounce_state {
72            BounceState::Reverse => {
73                self.index -= 1;
74            }
75            BounceState::Forward => {
76                self.index += 1;
77            }
78            BounceState::NoBounce => {}
79        }
80        ret
81    }
82}
83
84#[cfg(test)]
85mod tests {
86
87    use super::*;
88    #[test]
89    fn empty() {
90        let mut data: Vec<i32> = Vec::new();
91        let mut iter = BounceIterLockedMut::new(rwlockify(data.iter()).collect());
92        let expected: Vec<i32> = Vec::new();
93        assert_eq!(
94            *unrwlockify(iter).take(5).map(|x| *x).collect::<Vec<_>>(),
95            expected
96        );
97    }
98    #[test]
99    fn smol() {
100        let mut data = vec![1];
101        let mut iter = BounceIterLockedMut::new(rwlockify(data.iter()).collect());
102        let expected = vec![1, 1, 1, 1, 1];
103        assert_eq!(
104            *unrwlockify(iter).take(5).map(|x| *x).collect::<Vec<_>>(),
105            expected
106        );
107    }
108    #[test]
109    fn basic_test() {
110        let mut data = vec![1, 2, 3, 4, 5];
111        let expected = vec![1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5];
112        let mut iter = BounceIterLockedMut::new(rwlockify(data.iter()).collect());
113        assert_eq!(
114            *unrwlockify(iter).take(13).map(|x| *x).collect::<Vec<_>>(),
115            expected
116        );
117    }
118    #[test]
119    fn basic_test_rev() {
120        let mut data = vec![1, 2, 3, 4, 5];
121        let expected = vec![5, 4, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3, 4, 5];
122        let mut iter = BounceIterLockedMut::new_rev(rwlockify(data.iter()).collect());
123        assert_eq!(
124            *unrwlockify(iter).take(17).map(|x| *x).collect::<Vec<_>>(),
125            expected
126        );
127    }
128    #[test]
129    fn write() {
130        let ptrs: Vec<_> = rwlockify(vec![1, 2, 3, 4, 5].into_iter()).collect();
131        let expected = vec![2, 4, 6, 8, 10];
132        let mut iter = BounceIterLockedMut::new(ptrs);
133        for _ in 0..5 {
134            let Some(item) = iter.next() else {
135                break;
136            };
137            dbg!(&item);
138            let value = *item.read().unwrap();
139            *item.write().unwrap() = value * 2;
140            dbg!(&item);
141        }
142        iter.reset();
143        let data = unrwlockify(iter).take(5).collect::<Vec<_>>();
144        assert_eq!(data, expected);
145    }
146    #[test]
147    fn write_multiple() {
148        let ptrs: Vec<_> = rwlockify(vec![1, 2, 3, 4, 5].into_iter()).collect();
149        // is backward because it occurs after a bounce, and enabling peeking prevents us from calling reset()
150        let expected = vec![5, 10, 10, 2, 10];
151        let mut iter = BounceIterLockedMut::new(ptrs).peekable();
152        for _ in 0..5 {
153            let Some(item) = iter.next() else {
154                break;
155            };
156            // 2 is skipped as this applies to the NEXT input
157            let peek = iter.peek_mut().unwrap();
158            *peek.write().unwrap() = 5;
159            dbg!(&item);
160            let value = *item.read().unwrap();
161            *item.write().unwrap() = value * 2;
162            dbg!(&item);
163        }
164        let data = unrwlockify(iter).take(5).collect::<Vec<_>>();
165        assert_eq!(data, expected);
166    }
167}