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
use std::{mem::MaybeUninit, slice};
pub trait ContainerSizeGames<T> {
/// # Safety
/// `len` must be shorter than the current len
unsafe fn shorten(self, len: usize, value: T) -> Self;
/// # Safety
/// `len` must be shorter than the current len
unsafe fn shorten_with<F>(self, len: usize, f: F) -> Self
where
F: Fn() -> T;
/// # Safety
/// `len` must be longer than the current len
unsafe fn lengthen(self, len: usize, value: T) -> Self;
/// # Safety
/// `len` must be longer than the current len
unsafe fn lengthen_with<F>(self, len: usize, f: F) -> Self
where
F: Fn() -> T;
fn change_len(self, len: usize, value: T) -> Self;
fn zeroed(len: usize) -> Self;
}
impl<T> ContainerSizeGames<T> for Vec<T>
where
T: Copy + Default,
{
unsafe fn shorten(mut self, len: usize, value: T) -> Self {
debug_assert!(len <= self.len());
// SAFETY: this is safe if `len` is assumed to be smaller than the current length of the vector because that means everything up to `len` is alraedy initialized and that `len` is smaller than the vectors capacity (those are the requirements of `set_len`).
// I don't need to `drop` the ignored values (`self[len..self.len()]`) because `T` is `Copy` and thus is not `Drop`
unsafe {
self.set_len(len);
}
self.fill(value);
self
}
unsafe fn shorten_with<F>(mut self, len: usize, f: F) -> Self
where
F: FnMut() -> T,
{
debug_assert!(len <= self.len());
// SAFETY: this is safe if `len` is assumed to be smaller than the current length of the vector because that means everything up to `len` is alraedy initialized and that `len` is smaller than the vectors capacity (those are the requirements of `set_len`).
// I don't need to `drop` the ignored values (`self[len..self.len()]`) because `T` is `Copy` and thus is not `Drop`
unsafe {
self.set_len(len);
}
self.fill_with(f);
self
}
unsafe fn lengthen(mut self, len: usize, value: T) -> Self {
debug_assert!(len >= self.len());
// reserve capacity
self.reserve(len - self.len());
// fill up with value
let ptr = self.as_mut_ptr();
// SAFETY: ptr was just returned from `Vec::as_mut_ptr` so it should be fine, len is longer than `Vec::len` and thus uninitialized but that is Ok because the slice I'm creating is of `MaybeUninit`s
let slice: &mut [MaybeUninit<T>] = unsafe { slice::from_raw_parts_mut(ptr as *mut _, len) };
slice.fill(MaybeUninit::new(value));
// SAFETY: the capacity needed was reserved and the raw slice was filled with `value` and thus is initialized
unsafe {
self.set_len(len);
}
self
}
unsafe fn lengthen_with<F>(mut self, len: usize, f: F) -> Self
where
F: Fn() -> T,
{
debug_assert!(len >= self.len());
// reserve capacity
self.reserve(len - self.len());
// fill up with value
let ptr = self.as_mut_ptr();
// SAFETY: ptr was just returned from `Vec::as_mut_ptr` so it should be fine, len is longer than `Vec::len` and thus uninitialized but that is Ok because the slice I'm creating is of `MaybeUninit`s
let slice: &mut [MaybeUninit<T>] = unsafe { slice::from_raw_parts_mut(ptr as *mut _, len) };
slice.fill_with(|| MaybeUninit::new(f()));
// SAFETY: the capacity needed was reserved and the raw slice was filled with `value` and thus is initialized
unsafe {
self.set_len(len);
}
self
}
fn change_len(self, len: usize, value: T) -> Self {
if len > self.len() {
unsafe { self.lengthen(len, value) }
} else {
unsafe { self.shorten(len, value) }
}
}
fn zeroed(len: usize) -> Self {
let mut v = Self::new();
v.resize_with(len, T::default);
v
}
}