1pub struct ReusableVec<T> {
2 vec: Vec<T>,
3 len: usize,
4}
5
6impl<T> ReusableVec<T> {
7 #[inline]
8 pub fn new() -> Self {
9 Self { vec: Vec::new(), len: 0 }
10 }
11
12 #[inline]
13 pub fn with_capacity(capacity: usize) -> Self {
14 Self { vec: Vec::with_capacity(capacity), len: 0 }
15 }
16
17 #[inline]
18 pub fn push_reuse(&mut self) -> Option<&mut T> {
19 (self.len < self.vec.len()).then(move || {
20 self.len += 1;
21 &mut self.vec[self.len - 1]
22 })
23 }
24
25 #[inline]
26 pub fn push(&mut self, value: T) {
27 self.len = self.len.checked_add(1).unwrap();
28
29 if self.len <= self.vec.len() {
30 self.vec[self.len - 1] = value;
31 } else {
32 self.vec.push(value);
33 }
34 }
35
36 #[inline]
37 pub fn as_slice(&self) -> &[T] {
38 &self.vec[..self.len]
39 }
40
41 #[inline]
42 pub fn as_mut_slice(&mut self) -> &mut [T] {
43 &mut self.vec[..self.len]
44 }
45
46 #[inline]
47 pub fn into_vec(mut self) -> Vec<T> {
48 self.vec.truncate(self.len);
49 self.vec
50 }
51
52 #[inline]
53 pub fn clear_reuse(&mut self) {
54 self.len = 0;
55 }
56
57 #[inline]
58 pub fn clear_drop(&mut self) {
59 self.vec.clear();
60 self.len = 0;
61 }
62}
63
64impl<T> From<Vec<T>> for ReusableVec<T> {
65 #[inline]
66 fn from(vec: Vec<T>) -> Self {
67 Self { len: vec.len(), vec }
68 }
69}
70
71impl<T> From<ReusableVec<T>> for Vec<T> {
72 #[inline]
73 fn from(reusable: ReusableVec<T>) -> Vec<T> {
74 reusable.into_vec()
75 }
76}
77
78impl<T> std::ops::Deref for ReusableVec<T> {
79 type Target = [T];
80
81 #[inline]
82 fn deref(&self) -> &Self::Target {
83 self.as_slice()
84 }
85}
86
87impl<T> std::ops::DerefMut for ReusableVec<T> {
88 #[inline]
89 fn deref_mut(&mut self) -> &mut Self::Target {
90 self.as_mut_slice()
91 }
92}
93
94impl<T> IntoIterator for ReusableVec<T> {
95 type Item = T;
96 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
97
98 #[inline]
99 fn into_iter(self) -> Self::IntoIter {
100 self.into_vec().into_iter()
101 }
102}
103
104impl<'a, T> IntoIterator for &'a ReusableVec<T> {
105 type Item = &'a T;
106 type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
107
108 #[inline]
109 fn into_iter(self) -> Self::IntoIter {
110 self.as_slice().into_iter()
111 }
112}
113
114impl<'a, T> IntoIterator for &'a mut ReusableVec<T> {
115 type Item = &'a mut T;
116 type IntoIter = <&'a mut [T] as IntoIterator>::IntoIter;
117
118 #[inline]
119 fn into_iter(self) -> Self::IntoIter {
120 self.as_mut_slice().iter_mut()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn it_should_work() {
130 struct Thing {
131 cheap: u32,
132 expensive: Vec<u32>,
133 }
134
135 let mut things = ReusableVec::<Thing>::new();
136
137 for i in 0..2 {
138 let new_thing = Thing { cheap: 123, expensive: Vec::new() };
139
140 if let Some(reused) = things.push_reuse() {
141 let mut expensive = std::mem::take(&mut reused.expensive);
142
143 if i > 0 {
144 assert_eq!(expensive, [456]);
145 }
146
147 expensive.clear();
148 *reused = Thing { expensive, ..new_thing };
149 } else {
150 things.push(Thing { expensive: Vec::with_capacity(100), ..new_thing });
151 }
152
153 assert_eq!(things.len(), 1);
154 let last = things.last_mut().unwrap();
155 last.expensive.push(456);
156
157 assert_eq!(last.cheap, 123);
158 assert_eq!(last.expensive, [456]);
159
160 things.clear_reuse();
161 assert_eq!(things.len(), 0);
162 }
163
164 things.clear_drop();
165 assert_eq!(things.len(), 0);
166 assert!(things.push_reuse().is_none());
167
168 things.push(Thing { cheap: 0, expensive: Vec::new() });
169 things.clear_reuse();
170 assert_eq!(Vec::from(things).len(), 0);
171 }
172}