1use std::mem::MaybeUninit;
2use std::ptr::NonNull;
3
4#[inline]
6fn vec_len_offset_of_val<T>(vec: &mut Vec<T>) -> usize {
7 if std::mem::size_of::<T>() == 0 {
10 let mut vec: Vec<std::mem::MaybeUninit<T>> =
14 unsafe { std::mem::transmute(Vec::<T>::new()) };
15
16 vec.reserve(1);
18
19 let before: [usize; 3] = unsafe { std::mem::transmute_copy(&vec) };
20
21 unsafe {
24 vec.set_len(1);
25 }
26
27 let after: [usize; 3] = unsafe { std::mem::transmute_copy(&vec) };
28
29 match std::array::from_fn(|i| after[i] ^ before[i]) {
30 [_, 0, 0] => 0,
31 [0, _, 0] => 1,
32 [0, 0, _] => 2,
33 _ => unreachable!(),
34 }
35 } else {
36 vec.reserve(1);
40
41 let parts = unsafe {
43 let orig_len = vec.len();
44 vec.set_len(0);
45 let parts: [usize; 3] = std::mem::transmute_copy(&*vec);
46 vec.set_len(orig_len);
47 parts
48 };
49
50 match parts {
52 [0, a, b] if a != 0 && b != 0 => 0,
53 [a, 0, b] if a != 0 && b != 0 => 1,
54 [a, b, 0] if a != 0 && b != 0 => 2,
55 _ => unreachable!(),
56 }
57 }
58}
59
60#[inline]
64unsafe fn vec_split_at_spare_mut_with_len<T>(
65 vec: &mut Vec<T>,
66) -> (&mut [T], &mut [MaybeUninit<T>], &mut usize) {
67 let ptr = vec.as_mut_ptr();
68 let len = vec.len();
69 let cap = vec.capacity();
70
71 let spare_ptr = unsafe { ptr.add(len) }.cast::<MaybeUninit<T>>();
76 let spare_len = cap - len;
77
78 let len_mut = unsafe {
81 NonNull::new(vec as *mut Vec<T>)
82 .unwrap()
83 .cast::<usize>()
84 .add(vec_len_offset_of_val(vec))
85 .as_mut()
86 };
87
88 unsafe {
93 (
94 std::slice::from_raw_parts_mut(ptr, len),
95 std::slice::from_raw_parts_mut(spare_ptr, spare_len),
96 len_mut,
97 )
98 }
99}
100
101mod set_len_on_drop {
103 pub(super) struct SetLenOnDrop<'a> {
109 len: &'a mut usize,
110 local_len: usize,
111 }
112
113 impl<'a> SetLenOnDrop<'a> {
114 #[inline]
115 pub(super) fn new(len: &'a mut usize) -> Self {
116 SetLenOnDrop {
117 local_len: *len,
118 len,
119 }
120 }
121
122 #[inline]
123 pub(super) fn increment_len(&mut self, increment: usize) {
124 self.local_len += increment;
125 }
126 }
127
128 impl Drop for SetLenOnDrop<'_> {
129 #[inline]
130 fn drop(&mut self) {
131 *self.len = self.local_len;
132 }
133 }
134}
135
136use set_len_on_drop::SetLenOnDrop;
137
138#[cold]
139fn panic_exceeded_capacity() -> ! {
140 panic!("Insufficient capacity reserved to write all elements!")
141}
142
143pub struct Spare<'a, T> {
144 len_mut: &'a mut usize,
145 slots: std::slice::IterMut<'a, MaybeUninit<T>>,
146}
147
148impl<'a, T> Spare<'a, T> {
149 pub fn push(&mut self, item: T) {
150 let Some(slot) = self.slots.next() else {
151 panic_exceeded_capacity();
152 };
153 slot.write(item);
154 *self.len_mut += 1;
155 }
156}
157
158impl<T> std::iter::Extend<T> for Spare<'_, T> {
159 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
160 let mut len = SetLenOnDrop::new(self.len_mut);
161 for item in iter.into_iter() {
162 let Some(slot) = self.slots.next() else {
163 panic_exceeded_capacity();
164 };
165 slot.write(item);
166 len.increment_len(1);
167 }
168 }
169}
170
171impl<T> crate::SplitSpare<T> for Vec<T> {
172 type Spare<'a>
173 = Spare<'a, T>
174 where
175 Self: 'a;
176
177 fn split_spare<'s>(&'s mut self) -> (&'s mut [T], Self::Spare<'s>) {
178 let (initialized, spare, len_mut) = unsafe { vec_split_at_spare_mut_with_len(self) };
179 let spare = Spare {
180 len_mut,
181 slots: spare.iter_mut(),
182 };
183 (initialized, spare)
184 }
185
186 fn reserve_split_spare<'s>(&'s mut self, additional: usize) -> (&'s mut [T], Self::Spare<'s>) {
187 self.reserve(additional);
188 self.split_spare()
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use crate::SplitSpare;
195
196 #[test]
197 fn reserve_split_spare_works() {
198 let mut vec = vec![1, 2, 3];
199
200 let (init, mut spare) = vec.reserve_split_spare(3);
201
202 assert_eq!(init, &[1, 2, 3]);
203
204 spare.extend(init.iter().copied().map(|i| i + init.len()));
205
206 assert_eq!(vec, &[1, 2, 3, 4, 5, 6]);
207 }
208
209 #[test]
210 #[should_panic(expected = "Insufficient capacity reserved to write all elements!")]
211 fn exceed() {
212 let mut vec: Vec<i32> = Vec::new();
213
214 let (init, mut spare) = vec.split_spare();
215
216 assert_eq!(init, &[]);
217
218 spare.extend([1, 2, 3].iter().copied());
219 }
220}