1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use core::{marker::Destruct, mem::MaybeUninit, ops::Range};
pub(crate) struct Guard<'a, T> {
/// The array to be initialized.
pub array_mut: &'a mut [MaybeUninit<T>],
/// The number of items that have been initialized so far.
pub initialized: Range<usize>,
}
impl<T> Guard<'_, T> {
/// Adds an item to the array and updates the initialized item counter.
///
/// # Safety
///
/// No more than N elements must be initialized.
#[inline]
pub(crate) const unsafe fn push_back_unchecked(&mut self, item: T)
{
// SAFETY: If `initialized` was correct before and the caller does not
// invoke this method more than N times then writes will be in-bounds
// and slots will not be initialized more than once.
unsafe {
self.array_mut.get_unchecked_mut(self.initialized.end).write(item);
self.initialized.end = self.initialized.end.unchecked_add(1);
}
}
/// Adds an item to the array and updates the initialized item counter.
///
/// # Safety
///
/// No more than N elements must be initialized.
#[allow(unused)]
#[inline]
pub(crate) const unsafe fn push_front_unchecked(&mut self, item: T)
{
// SAFETY: If `initialized` was correct before and the caller does not
// invoke this method more than N times then writes will be in-bounds
// and slots will not be initialized more than once.
unsafe {
self.initialized.start = self.initialized.start.unchecked_sub(1);
self.array_mut.get_unchecked_mut(self.initialized.start).write(item);
}
}
#[inline]
pub(crate) const unsafe fn pop_back_unchecked(&mut self) -> T
{
// SAFETY: If `initialized` was correct before and the caller does not
// invoke this method more than N times then writes will be in-bounds
// and slots will not be initialized more than once.
unsafe {
self.initialized.end = self.initialized.end.unchecked_sub(1);
self.array_mut.get_unchecked_mut(self.initialized.end).assume_init_read()
}
}
#[inline]
pub(crate) const unsafe fn pop_front_unchecked(&mut self) -> T
{
// SAFETY: If `initialized` was correct before and the caller does not
// invoke this method more than N times then writes will be in-bounds
// and slots will not be initialized more than once.
unsafe {
let out = self.array_mut.get_unchecked_mut(self.initialized.start).assume_init_read();
self.initialized.start = self.initialized.start.unchecked_add(1);
out
}
}
}
impl<T> const Drop for Guard<'_, T>
where
T: ~const Destruct
{
#[inline]
fn drop(&mut self) {
debug_assert!(self.initialized.end <= self.array_mut.len());
debug_assert!(self.initialized.start <= self.initialized.end);
// SAFETY: this slice will contain only initialized objects.
unsafe {
self.array_mut.get_unchecked_mut(self.initialized.start..self.initialized.end).assume_init_drop();
}
}
}