1use std::cell::{Ref, RefCell, RefMut};
2
3
4pub struct DoubleBuffer<T> {
5 first: RefCell<T>,
6 second: RefCell<T>,
7 switched: bool,
8}
9
10impl<T> DoubleBuffer<T> {
23
24 pub fn new(current: T, next: T) -> Self {
25 Self {
26 first: RefCell::new(current),
27 second: RefCell::new(next),
28 switched: false,
29 }
30 }
31
32 pub fn current(&self) -> Ref<T> {
34 match self.switched {
35 false => self.first.borrow(),
36 true => self.second.borrow(),
37 }
38 }
39
40 pub fn next(&self) -> RefMut<T> {
42 match self.switched {
43 false => self.second.borrow_mut(),
44 true => self.first.borrow_mut(),
45 }
46 }
47
48 pub fn next_immut(&self) -> Ref<T> {
50 match self.switched {
51 false => self.second.borrow(),
52 true => self.first.borrow(),
53 }
54 }
55
56 pub fn switch(&mut self) {
58 self.switched = !self.switched;
59 }
60
61}
62
63
64#[cfg(test)]
65mod tests {
66 use crate::DoubleBuffer;
67
68
69 #[test]
70 fn switching_buffers_works() {
71 let mut my_double_buf: DoubleBuffer<i32> = DoubleBuffer::new(0,0);
72 *my_double_buf.next() += 10;
73 assert_eq!(*my_double_buf.current(), 0);
74 my_double_buf.switch();
75 assert_eq!(*my_double_buf.current(), 10);
76 my_double_buf.switch();
77 assert_eq!(*my_double_buf.current(), 0);
78 }
79
80
81 #[test]
82 fn writing_from_current_to_next_works() {
83 let mut my_double_buf: DoubleBuffer<Vec<i32>> = DoubleBuffer::new( vec!(2,4,6), Vec::new());
84 for number in my_double_buf.current().iter() {
85 my_double_buf.next().push(*number + 1);
86 }
87 my_double_buf.switch();
88 assert_eq!(*my_double_buf.current(), vec!(3,5,7));
89 *my_double_buf.next() = Vec::new();
90 for number in my_double_buf.current().iter() {
91 my_double_buf.next().push(*number + 1);
92 }
93 my_double_buf.switch();
94 assert_eq!(*my_double_buf.current(), vec!(4,6,8));
95
96 }
97
98
99}