1use core::{
2 borrow::{Borrow, BorrowMut},
3 fmt,
4 marker::PhantomData,
5 mem::MaybeUninit,
6 ops,
7 ptr::{self, NonNull},
8 slice::{self, from_raw_parts_mut},
9};
10
11pub struct InlineVec<T, const N: usize> {
13 elements: [MaybeUninit<T>; N],
14 len: usize,
15}
16
17impl<T, const N: usize> Drop for InlineVec<T, N> {
18 fn drop(&mut self) {
19 self.clear()
20 }
21}
22
23unsafe impl<T: Send, const N: usize> Send for InlineVec<T, N> {}
26
27unsafe impl<T: Sync, const N: usize> Sync for InlineVec<T, N> {}
30
31impl<T, const N: usize> InlineVec<T, N> {
32 pub fn new() -> Self {
36 Self {
37 elements: unsafe { MaybeUninit::uninit().assume_init() },
38 len: 0,
39 }
40 }
41
42 pub fn clear(&mut self) {
44 let len = self.len;
45 self.len = 0;
46
47 for i in 0..len {
48 unsafe {
49 self.elements[i].as_mut_ptr().drop_in_place();
50 }
51 }
52 }
53
54 pub fn as_mut_ptr(&mut self) -> *mut T {
59 self.elements.as_mut_ptr().cast()
60 }
61
62 pub fn as_mut_slice(&mut self) -> &mut [T] {
66 unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) }
67 }
68
69 pub fn as_ptr(&self) -> *const T {
80 self.elements.as_ptr().cast()
81 }
82
83 pub fn as_slice(&self) -> &[T] {
87 unsafe { slice::from_raw_parts(self.as_ptr(), self.len) }
88 }
89
90 pub const fn capacity(&self) -> usize {
92 N
93 }
94
95 pub fn reserve(&mut self, additional: usize) {
102 if N - self.len < additional {
103 Self::out_of_space();
104 }
105 }
106
107 #[cold]
108 fn out_of_space() -> ! {
109 panic!(
110 "reserve requested more capacity than the InlineVec has available"
111 );
112 }
113
114 pub fn is_empty(&self) -> bool {
116 self.len == 0
117 }
118
119 pub fn len(&self) -> usize {
122 self.len
123 }
124
125 pub fn extend_from_slice(&mut self, other: &[T]) {
129 if !other.is_empty() {
130 self.reserve(other.len());
131 unsafe {
132 core::ptr::copy_nonoverlapping(
133 other.as_ptr(),
134 self.as_mut_ptr().add(self.len()),
135 other.len(),
136 );
137 }
138 self.len += other.len();
139 }
140 }
141
142 pub fn pop(&mut self) -> Option<T> {
145 if self.len == 0 {
146 None
147 } else {
148 unsafe {
149 self.len -= 1;
150 Some(self.as_ptr().add(self.len()).read())
151 }
152 }
153 }
154
155 pub unsafe fn push_unchecked(&mut self, value: T) {
162 unsafe {
163 self.as_mut_ptr().add(self.len).write(value);
164 self.len += 1;
165 }
166 }
167
168 pub fn push(&mut self, value: T) {
170 if self.len == N {
171 Self::out_of_space()
172 } else {
173 unsafe {
174 self.push_unchecked(value);
175 }
176 }
177 }
178
179 pub fn reserve_exact(&mut self, additional: usize) {
189 self.reserve(additional);
190 }
191
192 pub unsafe fn set_len(&mut self, new_len: usize) {
202 debug_assert!(new_len <= self.capacity());
203
204 self.len = new_len;
205 }
206
207 pub fn drain(&mut self) -> Drain<'_, T, N> {
210 let remaining = self.len();
211 unsafe {
212 self.set_len(0);
213 }
214
215 Drain {
216 current: unsafe { NonNull::new_unchecked(self.as_mut_ptr()) },
217 remaining,
218 _phantom: PhantomData,
219 }
220 }
221}
222
223impl<T, const N: usize> InlineVec<MaybeUninit<T>, N> {
224 pub fn assume_init(self) -> InlineVec<T, N> {
233 let mut elements = unsafe {
234 MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init()
235 };
236 unsafe {
237 ptr::copy_nonoverlapping(
238 self.elements.as_ptr().cast(),
239 elements.as_mut_ptr(),
240 N,
241 );
242 }
243 InlineVec {
244 elements,
245 len: self.len,
246 }
247 }
248}
249
250impl<T, const N: usize> AsMut<[T]> for InlineVec<T, N> {
251 fn as_mut(&mut self) -> &mut [T] {
252 self.as_mut_slice()
253 }
254}
255
256impl<T, const N: usize> AsRef<[T]> for InlineVec<T, N> {
257 fn as_ref(&self) -> &[T] {
258 self.as_slice()
259 }
260}
261
262impl<T, const N: usize> Borrow<[T]> for InlineVec<T, N> {
263 fn borrow(&self) -> &[T] {
264 self.as_slice()
265 }
266}
267
268impl<T, const N: usize> BorrowMut<[T]> for InlineVec<T, N> {
269 fn borrow_mut(&mut self) -> &mut [T] {
270 self.as_mut_slice()
271 }
272}
273
274impl<T: fmt::Debug, const N: usize> fmt::Debug for InlineVec<T, N> {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 self.as_slice().fmt(f)
277 }
278}
279
280impl<T, const N: usize> Default for InlineVec<T, N> {
281 fn default() -> Self {
282 Self::new()
283 }
284}
285
286impl<T, const N: usize> ops::Deref for InlineVec<T, N> {
287 type Target = [T];
288
289 fn deref(&self) -> &Self::Target {
290 self.as_slice()
291 }
292}
293
294impl<T, const N: usize> ops::DerefMut for InlineVec<T, N> {
295 fn deref_mut(&mut self) -> &mut Self::Target {
296 self.as_mut_slice()
297 }
298}
299
300impl<T, I: slice::SliceIndex<[T]>, const N: usize> ops::Index<I>
301 for InlineVec<T, N>
302{
303 type Output = <I as slice::SliceIndex<[T]>>::Output;
304
305 fn index(&self, index: I) -> &Self::Output {
306 &self.as_slice()[index]
307 }
308}
309
310impl<T, I: slice::SliceIndex<[T]>, const N: usize> ops::IndexMut<I>
311 for InlineVec<T, N>
312{
313 fn index_mut(&mut self, index: I) -> &mut Self::Output {
314 &mut self.as_mut_slice()[index]
315 }
316}
317
318pub struct Drain<'a, T: 'a, const N: usize> {
323 current: NonNull<T>,
324 remaining: usize,
325 _phantom: PhantomData<&'a mut InlineVec<T, N>>,
326}
327
328impl<T: fmt::Debug, const N: usize> fmt::Debug for Drain<'_, T, N> {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 f.debug_tuple("Drain").field(&self.as_slice()).finish()
331 }
332}
333
334impl<T, const N: usize> Drain<'_, T, N> {
335 pub fn as_slice(&self) -> &[T] {
337 unsafe { from_raw_parts_mut(self.current.as_ptr(), self.remaining) }
338 }
339}
340
341impl<T, const N: usize> AsRef<[T]> for Drain<'_, T, N> {
342 fn as_ref(&self) -> &[T] {
343 self.as_slice()
344 }
345}
346
347impl<T, const N: usize> Iterator for Drain<'_, T, N> {
348 type Item = T;
349
350 fn next(&mut self) -> Option<T> {
351 if self.remaining > 0 {
352 self.remaining -= 1;
353 let result = unsafe { self.current.as_ptr().read() };
354 self.current =
355 unsafe { NonNull::new_unchecked(self.current.as_ptr().add(1)) };
356 Some(result)
357 } else {
358 None
359 }
360 }
361
362 fn size_hint(&self) -> (usize, Option<usize>) {
363 (self.remaining, Some(self.remaining))
364 }
365}
366
367impl<T, const N: usize> DoubleEndedIterator for Drain<'_, T, N> {
368 fn next_back(&mut self) -> Option<T> {
369 if self.remaining > 0 {
370 self.remaining -= 1;
371 unsafe { Some(self.current.as_ptr().add(self.remaining).read()) }
372 } else {
373 None
374 }
375 }
376}
377
378impl<T, const N: usize> Drop for Drain<'_, T, N> {
379 fn drop(&mut self) {
380 for i in 0..self.remaining {
381 unsafe {
382 self.current.as_ptr().add(i).drop_in_place();
383 }
384 }
385 }
386}
387
388impl<T, const N: usize> ExactSizeIterator for Drain<'_, T, N> {}
389
390impl<T, const N: usize> core::iter::FusedIterator for Drain<'_, T, N> {}
391
392#[cfg(test)]
393mod tests {
394 use crate::util::InlineVec;
395
396 #[test]
397 fn drain() {
398 let mut vec = InlineVec::<_, 8>::new();
399
400 for i in 0..100 {
401 vec.push(i);
402 if vec.len() == vec.capacity() {
403 for j in vec.drain() {
404 let _ = j;
405 }
406 }
407 }
408 }
409}