reusable_vec/
lib.rs

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}