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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
use ptr;
pub
/// A trait of custom spare memory policies.
///
/// A spare memory policy defines the way a *cds* collection handles spare memory.
///
/// This includes both the initial allocation, and any memory that becomes free following removal of
/// an element from a collection (including removal forced by a [`drop`] of a collection).
///
/// Note that spare memory policy affects only the current region of memory occupied by a
/// collection. That is, if a program moves a whole collection (e.g. `ArrayVec`), the old region of
/// memory occupied by the collection is no longer accessible, and spare memory policy cannot be
/// applied to it. This may lead to having the old region of memory a bytewise copy of
/// the memory the collection was moved to.
///
/// Currently the following policies are supported:
///
/// - [`Uninitialized`] does nothing with spare bytes
/// - [`Zeroed`] fills spare bytes with zeroes
/// - [`Pattern`] fills spare bytes with a specified value
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "arrayvec")]
/// use cds::{
/// arrayvec::ArrayVec,
/// len::U8,
/// mem::{Uninitialized, Pattern, Zeroed},
/// };
/// use core::convert::TryFrom;
/// # #[cfg(feature = "arrayvec")]
/// # fn example() -> Result<(), cds::arrayvec::errors::InsufficientCapacityError> {
///
/// // --- Uninitialized ---
///
/// type A = ArrayVec<u16, 3, U8, Uninitialized>;
///
/// // all memory is uninitialized
/// let mut a = A::new();
///
/// // all memory except for the first element is uninitialized
/// let mut a = A::try_from([1])?;
/// assert_eq!(unsafe { a.as_ptr().read() }, 1);
///
/// // spare memory remains a bytewise copy of elements previously stored there
/// assert_eq!(a.pop(), Some(1));
/// assert_eq!(unsafe { a.as_ptr().read() }, 1);
///
///
/// // --- Pattern ---
///
/// type B = ArrayVec<u16, 3, U8, Pattern<0xAB>>;
///
/// // all memory is initialized with P
/// let mut a = B::new();
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 0xABAB);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0xABAB);
/// assert_eq!(unsafe { a.as_ptr().add(2).read() }, 0xABAB);
///
/// // all memory except for the first two elements is initialized with P
/// let mut a = B::try_from([1, 2])?;
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 0x1);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0x2);
/// assert_eq!(unsafe { a.as_ptr().add(2).read() }, 0xABAB);
///
/// // spare memory is initialized with P after removal of an element
/// assert_eq!(a.remove(0), 1);
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 0x2);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0xABAB);
/// assert_eq!(unsafe { a.as_ptr().add(2).read() }, 0xABAB);
///
///
/// // --- Zeroed ---
///
/// type C = ArrayVec<u16, 2, U8, Zeroed>;
///
/// // all memory is zeroed
/// let a = C::new();
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 0);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0);
///
/// // all memory except for the first element is zeroed
/// let mut a = C::try_from([3])?;
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 3);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0);
///
/// // spare memory is zeroed after removal of an element
/// assert_eq!(a.pop(), Some(3));
/// assert_eq!(unsafe { a.as_ptr().add(0).read() }, 0);
/// assert_eq!(unsafe { a.as_ptr().add(1).read() }, 0);
/// # Ok(())
/// # }
/// # #[cfg(feature = "arrayvec")]
/// # example().expect("example failed");
/// ```
///
/// [`drop`]: https://doc.rust-lang.org/core/mem/fn.drop.html
/// Uninitialized spare memory policy.
///
/// `Uninitialized` is the fastest spare memory policy, because it does absolutely nothing.
///
/// This means that:
/// - initial memory allocated by a collection remains uninitialized
/// - a region of memory occupied by an element remains a bytewise copy of the
/// element after it is moved out, until the region is overwritten (if at all)
/// - a region of memory occupied by a collection remains untouched when the collection is dropped,
/// until the region is overwritten (if at all)
;
/// Pattern-initialized spare memory policy.
///
/// Written as `Pattern<P>`, pattern spare memory policy initializes every spare byte with the value
/// `P`.
///
/// This means that:
/// - initial memory allocated by a collection is bytewise initialized with the value `P`
/// - a region of memory occupied by an element is bytewise initialized with the value `P`
/// when the element is moved out, unless the region is immediately overwritten with another
/// element
/// - when a collection is dropped all memory of elements dropped with the collection is
/// bytewise initialized with the value `P`
;
/// Zeroed spare memory policy.
///
/// This is a friendly alias for [`Pattern`] using zero as the pattern byte.
pub type Zeroed = ;