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}