temporary_annex/
lib.rs

1use core::ops::Deref;
2
3pub struct Annex<'a, T: Annexable>(&'a mut T);
4
5impl<'a, T: Annexable> Annex<'a, T> {
6    pub fn new(item: &'a mut T) -> Annex<'a, T> {
7        Annex(item)
8    }
9
10    pub fn push_annex(&mut self, item: T::NewItem) -> Annex<T> {
11        self.0.push_annex(item)
12    }
13}
14
15pub trait Annexable {
16    type NewItem;
17
18    fn push_annex(&mut self, item: Self::NewItem) -> Annex<Self>
19    where
20        Self: Sized;
21    fn revert_annex(&mut self);
22}
23
24impl<T> Annexable for std::vec::Vec<T> {
25    type NewItem = T;
26
27    fn push_annex(&mut self, item: Self::NewItem) -> Annex<Self> {
28        self.push(item);
29        Annex(self)
30    }
31
32    fn revert_annex(&mut self) {
33        self.pop();
34    }
35}
36
37impl<T: Annexable> Deref for Annex<'_, T> {
38    type Target = T;
39
40    fn deref(&self) -> &Self::Target {
41        self.0
42    }
43}
44
45// TODO could do this but allowing it my break the symmetry if self is mutated between the drop
46// impl<T: Annexable> DerefMut for Annex<'_, T> {
47//     fn deref_mut(&mut self) -> &mut Self::Target {
48//         &mut self.0
49//     }
50// }
51
52impl<'a, T: Annexable> Drop for Annex<'a, T> {
53    fn drop(&mut self) {
54        Annexable::revert_annex(self.0);
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::Annexable;
61
62    #[test]
63    fn it_works() {
64        let mut vec1 = vec![1, 2, 3];
65        assert_eq!(vec1, [1, 2, 3]);
66        {
67            let mut new_vec_ref = vec1.push_annex(4);
68            assert_eq!(*new_vec_ref, [1, 2, 3, 4]);
69            {
70                let new_new_vec_ref = new_vec_ref.push_annex(8);
71                assert_eq!(*new_new_vec_ref, [1, 2, 3, 4, 8]);
72            }
73            assert_eq!(*new_vec_ref, [1, 2, 3, 4]);
74        }
75        assert_eq!(vec1, [1, 2, 3]);
76    }
77}