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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use core::mem::{align_of, size_of, MaybeUninit};
use super::{Storage, StorageWithCapacity};
#[repr(C)]
struct AlignedBuffer<T, A> {
align: MaybeUninit<[A; 0]>,
value: T,
}
#[repr(transparent)]
pub struct UninitBuffer<T, A = u8>(MaybeUninit<AlignedBuffer<T, A>>);
unsafe impl<T, A> Send for UninitBuffer<T, A> {}
unsafe impl<T, A> Sync for UninitBuffer<T, A> {}
const fn size<U, T, A>() -> usize {
if size_of::<U>() == 0 {
usize::MAX
} else {
size_of::<AlignedBuffer<T, A>>() / size_of::<U>()
}
}
impl<T, A> UninitBuffer<T, A> {
pub const fn capacity<U>() -> usize { size::<U, T, A>() }
pub const fn uninit() -> Self { Self(MaybeUninit::uninit()) }
pub const fn new(value: T) -> Self {
Self(MaybeUninit::new(AlignedBuffer {
align: MaybeUninit::uninit(),
value,
}))
}
}
impl<T, A> Default for UninitBuffer<T, A> {
fn default() -> Self { Self::uninit() }
}
impl<T, A> Clone for UninitBuffer<T, A> {
fn clone(&self) -> Self { Self::default() }
}
unsafe impl<U, T, A> StorageWithCapacity<U> for UninitBuffer<T, A> {
fn with_capacity(capacity: usize) -> Self {
let max_capacity = size::<U, T, A>();
if capacity > max_capacity {
crate::raw::capacity::fixed_capacity_reserve_error(max_capacity, capacity)
}
Self::default()
}
#[inline]
#[doc(hidden)]
#[allow(non_snake_case)]
fn __with_capacity__const_capacity_checked(capacity: usize, old_capacity: Option<usize>) -> Self {
match old_capacity {
Some(old_capacity) if old_capacity <= size::<U, T, A>() => Self::default(),
_ => StorageWithCapacity::<U>::with_capacity(capacity),
}
}
}
unsafe impl<U, T, A> Storage<U> for UninitBuffer<T, A> {
#[doc(hidden)]
const CONST_CAPACITY: Option<usize> = Some(size::<U, T, A>());
const IS_ALIGNED: bool = align_of::<AlignedBuffer<T, A>>() >= align_of::<U>();
fn capacity(&self) -> usize { size::<U, T, A>() }
fn as_ptr(&self) -> *const U { self.0.as_ptr().cast() }
fn as_mut_ptr(&mut self) -> *mut U { self.0.as_mut_ptr().cast() }
fn reserve(&mut self, new_capacity: usize) {
let capacity = size::<U, T, A>();
if new_capacity > capacity {
crate::raw::capacity::fixed_capacity_reserve_error(capacity, new_capacity)
}
}
fn try_reserve(&mut self, capacity: usize) -> bool { capacity <= size::<U, T, A>() }
}