structures/array/lazy.rs
1//! Extension to make working with LazyArray easier.
2
3use super::LazyArray;
4use std::{
5 mem::{MaybeUninit, transmute},
6 ptr::drop_in_place,
7};
8
9impl<T> LazyArray<T> {
10 /// Get reference to an slice of elements assuming they were initialized.
11 ///
12 /// # Safety
13 ///
14 /// It is up to the caller to ensure elements are indeed initialized.
15 ///
16 /// # Panic
17 ///
18 /// Panics if reads beyond end of the array.
19 ///
20 /// # Arguments
21 ///
22 /// * `index` - Starting index (inclusive) of the slice.
23 /// * `len` - Number of elements including the starting index.
24 ///
25 /// # Examples
26 ///
27 /// ```
28 /// # use structures::Array;
29 /// let mut array = Array::lazy(10);
30 ///
31 /// // Copy elements into the array.
32 /// let elems: Vec<_> = (0..10).collect();
33 /// array.copy_from_slice(0, &elems);
34 ///
35 /// // Make sure copied correctly.
36 /// assert_eq!(unsafe { array.assume_init(0, elems.len()) }, &elems);
37 /// ```
38 #[inline]
39 pub unsafe fn assume_init(&self, index: usize, len: usize) -> &[T] {
40 // Safety: It is the responsibility of the caller to ensure memory
41 // is actually initialized in the given range. T has the same size
42 // and alignment as MaybeUninit<T>.
43 unsafe { transmute(&self[index..index + len]) }
44 }
45
46 /// Get a mutable reference to an slice of elements assuming they were initialized.
47 ///
48 /// # Safety
49 ///
50 /// It is up to the caller to ensure elements are indeed initialized.
51 ///
52 /// # Panic
53 ///
54 /// Panics if reads beyond end of the array.
55 ///
56 /// # Arguments
57 ///
58 /// * `index` - Starting index (inclusive) of the slice.
59 /// * `len` - Number of elements including the starting index.
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// # use structures::Array;
65 /// let mut array = Array::lazy(10);
66 ///
67 /// // Initialize elements.
68 /// let elems: Vec<_> = (0..10).map(|_| vec![1, 2, 3]).collect();
69 /// array.write_from_slice(0, &elems);
70 ///
71 /// // Mutate for elements.
72 /// for elem in unsafe { array.assume_init_mut(0, elems.len()) } {
73 /// elem.clear();
74 /// }
75 ///
76 /// // Make sure array was mutated correctly.
77 /// let elems: Vec<_> = (0..10).map(|_| vec![]).collect();
78 /// assert_eq!(unsafe { array.assume_init(0, elems.len()) }, &elems);
79 ///
80 /// // Don't forget to drop elements!
81 /// unsafe { array.assume_init_drop(0, elems.len()) };
82 /// ```
83 #[inline]
84 pub unsafe fn assume_init_mut(&mut self, index: usize, len: usize) -> &mut [T] {
85 // Safety: It is the responsibility of the caller to ensure memory
86 // is actually initialized in the given range. T has the same size
87 // and alignment as MaybeUninit<T>.
88 unsafe { transmute(&mut self[index..index + len]) }
89 }
90
91 /// Drop a slice of elements assuming they were initialized.
92 ///
93 /// # Safety
94 ///
95 /// It is up to the caller to ensure elements are indeed initialized.
96 ///
97 /// # Panic
98 ///
99 /// Panics if reads beyond end of the array.
100 ///
101 /// # Arguments
102 ///
103 /// * `index` - Starting index (inclusive) of the slice.
104 /// * `len` - Number of elements including the starting index.
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// # use structures::Array;
110 /// let mut array = Array::lazy(10);
111 ///
112 /// // Initialize elements.
113 /// let elems: Vec<_> = (0..10).map(|_| vec![11, 72, 93]).collect();
114 /// array.write_from_slice(0, &elems);
115 ///
116 /// // Make sure elements are dropped.
117 /// unsafe { array.assume_init_drop(0, elems.len()) };
118 /// ```
119 #[inline]
120 pub unsafe fn assume_init_drop(&mut self, index: usize, len: usize) {
121 // Safety: It is the responsibility of the caller to ensure memory
122 // is actually initialized in the given range.
123 unsafe {
124 let to_drop = self.assume_init_mut(index, len);
125 drop_in_place(to_drop);
126 }
127 }
128}
129
130impl<T: Clone> LazyArray<T> {
131 /// Initialize a slice of elements with another slice.
132 ///
133 /// # Safety
134 ///
135 /// This method does not execute `drop` on the slice of elements in array.
136 /// This might result in resource leaks in certain cases. To execute drop
137 /// before write see [`LazyArray::overwrite_from_slice`] instead.
138 ///
139 /// Rust does not consider resource leaks an unsafe operation, so this method
140 /// is not marked as unsafe.
141 ///
142 /// # Panic
143 ///
144 /// Panics if reads beyond end of the array.
145 ///
146 /// # Arguments
147 ///
148 /// * `index` - Starting index (inclusive) of the slice.
149 /// * `elems` - Elements to overwrite slice with.
150 ///
151 /// # Examples
152 ///
153 /// ```
154 /// # use structures::Array;
155 /// let mut array = Array::lazy(10);
156 ///
157 /// // Initialize elements.
158 /// let elems: Vec<_> = (0..10).map(|_| vec![1, 2, 3]).collect();
159 /// assert_eq!(array.write_from_slice(0, &elems), &elems);
160 ///
161 /// // Don't forget to drop elements!
162 /// unsafe { array.assume_init_drop(0, elems.len()) };
163 /// ```
164 #[inline]
165 pub fn write_from_slice(&mut self, index: usize, elems: &[T]) -> &mut [T] {
166 for (dst, src) in self[index..index + elems.len()].iter_mut().zip(elems) {
167 dst.write(src.clone());
168 }
169
170 // Safety: We just initialized these elements.
171 unsafe { transmute(self.assume_init_mut(index, elems.len())) }
172 }
173
174 /// Overwrite a slice of elements with another slice.
175 ///
176 /// # Safety
177 ///
178 /// It is up to the caller to ensure elements are indeed initialized.
179 ///
180 /// # Panic
181 ///
182 /// Panics if reads beyond end of the array.
183 ///
184 /// # Arguments
185 ///
186 /// * `index` - Starting index (inclusive) of the slice.
187 /// * `elems` - Elements to overwrite slice with.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// # use structures::Array;
193 /// let mut array = Array::lazy(10);
194 ///
195 /// // First initialize elements.
196 /// let elems: Vec<_> = (0..10).map(|_| vec![1, 2, 3]).collect();
197 /// assert_eq!(array.write_from_slice(0, &elems), &elems);
198 ///
199 /// // Then overwrite them.
200 /// let elems: Vec<_> = (0..10).map(|_| vec![4, 5, 6]).collect();
201 /// assert_eq!(unsafe { array.overwrite_from_slice(0, &elems) }, &elems);
202 ///
203 /// // Don't forget to drop elements!
204 /// unsafe { array.assume_init_drop(0, elems.len()) };
205 /// ```
206 #[inline]
207 pub unsafe fn overwrite_from_slice(&mut self, index: usize, elems: &[T]) -> &mut [T] {
208 for (dst, src) in self[index..index + elems.len()].iter_mut().zip(elems) {
209 // Safety: It is the responsibility of the caller to ensure memory
210 // is actually initialized in the given range.
211 unsafe { dst.assume_init_drop() };
212
213 dst.write(src.clone());
214 }
215
216 // Safety: We just initialized these elements.
217 unsafe { transmute(self.assume_init_mut(index, elems.len())) }
218 }
219}
220
221impl<T: Copy> LazyArray<T> {
222 /// Copy elements from a slice into the array.
223 ///
224 /// # Panic
225 ///
226 /// * If the slice overflows bounds of the array.
227 ///
228 /// # Arguments
229 ///
230 /// * `index` - Index to start writes.
231 /// * `elems` - Elements to copy into array.
232 ///
233 /// # Examples
234 ///
235 /// ```
236 /// # use structures::Array;
237 /// let mut array = Array::lazy(10);
238 ///
239 /// // Copy elements into the array.
240 /// let elems: Vec<_> = (0..10).collect();
241 /// assert_eq!(array.copy_from_slice(0, &elems), &elems);
242 /// assert_eq!(unsafe { array.assume_init(0, elems.len()) }, &elems);
243 /// ```
244 #[inline]
245 pub fn copy_from_slice(&mut self, index: usize, elems: &[T]) -> &mut [T] {
246 let end_index = index + elems.len();
247
248 // Safety: T has the same size and alignment as MaybeUnint<T>.
249 let src: &[MaybeUninit<T>] = unsafe { transmute(elems) };
250 self[index..end_index].copy_from_slice(src);
251
252 // Safety:
253 // * Index of elements have definitely been initialized.
254 // * T has the same size and alignment as MaybeUnint<T>.
255 unsafe { transmute(&mut self[index..end_index]) }
256 }
257}