1#![expect(
2 unsafe_op_in_unsafe_fn,
3 reason = "Array requires unsafe code in some places"
4)]
5
6use std::alloc;
9use std::ops::{Deref, DerefMut, Index, IndexMut};
10
11#[derive(Debug, thiserror::Error)]
13pub enum ArrayCreationError {
14 #[error("allocation error: {0}")]
15 AllocationError(String),
16
17 #[error("layout error: {0}")]
18 LayoutError(#[from] alloc::LayoutError),
19}
20
21pub struct Array<T> {
44 ptr: *mut T,
45 size: usize,
46}
47
48impl<T> Array<T> {
49 pub fn new(size: usize) -> Result<Self, ArrayCreationError> {
53 unsafe {
54 let layout = alloc::Layout::array::<T>(size)?;
58 let ptr = alloc::alloc(layout) as *mut T;
59
60 if ptr.is_null() {
61 return Err(ArrayCreationError::AllocationError(
62 "null pointer".to_owned(),
63 ));
64 }
65
66 Ok(Self { ptr, size })
67 }
68 }
69
70 #[must_use]
72 pub const fn size(&self) -> usize {
73 self.size
74 }
75
76 #[must_use]
78 pub const fn as_ptr(&self) -> *const T {
79 self.ptr
80 }
81
82 #[must_use]
84 pub const fn as_mut_ptr(&self) -> *mut T {
85 self.ptr
86 }
87
88 pub fn set(&mut self, index: usize, value: T) {
94 if index >= self.size {
95 panic!("index out of bounds");
96 }
97
98 unsafe { *(self.ptr.add(index)) = value }
101 }
102
103 #[must_use]
105 pub const fn get(&self, index: usize) -> Option<&T> {
106 if index >= self.size {
107 return None;
108 }
109
110 unsafe { Some(&(*(self.ptr.add(index)))) }
113 }
114
115 #[must_use]
117 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
118 if index >= self.size {
119 return None;
120 }
121
122 unsafe { Some(&mut (*(self.ptr.add(index)))) }
125 }
126
127 #[must_use]
133 pub const unsafe fn get_ptr(&self, index: usize) -> *const T {
134 self.ptr.add(index) as *const T
135 }
136
137 #[must_use]
143 pub unsafe fn get_ptr_mut(&mut self, index: usize) -> *mut T {
144 self.ptr.add(index)
145 }
146
147 #[must_use]
149 pub fn iter(&self) -> iter::Iter<'_, T> {
150 iter::Iter::new(self)
151 }
152
153 #[must_use]
155 pub fn iter_mut(&mut self) -> iter::IterMut<'_, T> {
156 iter::IterMut::new(self)
157 }
158}
159
160impl<T> Drop for Array<T> {
161 fn drop(&mut self) {
162 unsafe {
163 self.ptr.drop_in_place();
164 }
165 }
166}
167
168impl<T> Deref for Array<T> {
169 type Target = [T];
170
171 fn deref(&self) -> &Self::Target {
172 unsafe { std::slice::from_raw_parts(self.ptr, self.size) }
174 }
175}
176
177impl<T> DerefMut for Array<T> {
178 fn deref_mut(&mut self) -> &mut Self::Target {
179 unsafe { std::slice::from_raw_parts_mut(self.ptr, self.size) }
181 }
182}
183
184impl<T> AsRef<[T]> for Array<T> {
185 fn as_ref(&self) -> &[T] {
186 self
187 }
188}
189
190impl<T> AsMut<[T]> for Array<T> {
191 fn as_mut(&mut self) -> &mut [T] {
192 &mut *self
193 }
194}
195
196impl std::io::Write for Array<u8> {
198 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
200 let mut index = 0;
201 for b in buf {
202 self[index] = *b;
203 index += 1;
204 }
205 Ok(index + 1)
206 }
207
208 fn flush(&mut self) -> std::io::Result<()> {
209 Ok(())
210 }
211}
212
213impl<T> Index<usize> for Array<T> {
214 type Output = T;
215
216 fn index(&self, index: usize) -> &Self::Output {
217 self.get(index).expect("index out of bounds")
218 }
219}
220
221impl<T> IndexMut<usize> for Array<T> {
222 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
223 self.get_mut(index).expect("index out of bounds")
224 }
225}
226
227impl<T: Clone> Clone for Array<T> {
228 fn clone(&self) -> Self {
229 let mut array = Array::new(self.size).expect("allocation failed");
230
231 for (i, v) in self.iter().enumerate() {
232 array[i] = v.clone();
233 }
234
235 array
236 }
237}
238
239impl<T> IntoIterator for Array<T> {
240 type Item = T;
241 type IntoIter = iter::IntoIter<T>;
242
243 fn into_iter(self) -> Self::IntoIter {
244 iter::IntoIter::new(self)
245 }
246}
247
248impl<'a, T> IntoIterator for &'a Array<T> {
249 type Item = &'a T;
250 type IntoIter = iter::Iter<'a, T>;
251
252 fn into_iter(self) -> Self::IntoIter {
253 self.iter()
254 }
255}
256
257impl<'a, T> IntoIterator for &'a mut Array<T> {
258 type Item = &'a mut T;
259 type IntoIter = iter::IterMut<'a, T>;
260
261 fn into_iter(self) -> Self::IntoIter {
262 self.iter_mut()
263 }
264}
265
266pub mod iter {
267 use super::Array;
268 use std::marker::PhantomData;
269
270 pub struct Iter<'a, T> {
272 _marker: PhantomData<&'a T>,
273 ptr: *const T,
274 end: *const T,
275 }
276
277 impl<'a, T> Iter<'a, T> {
278 pub(crate) fn new(array: &'a Array<T>) -> Self {
279 let ptr = array.ptr;
280 Self {
281 _marker: PhantomData,
282 ptr,
283 end: unsafe { ptr.add(array.size) },
284 }
285 }
286 }
287
288 impl<'a, T> Iterator for Iter<'a, T> {
289 type Item = &'a T;
290
291 fn next(&mut self) -> Option<Self::Item> {
292 if self.ptr == self.end {
293 None
294 } else {
295 unsafe {
296 let ptr = self.ptr;
297 self.ptr = self.ptr.add(1);
298 Some(&*ptr)
299 }
300 }
301 }
302 }
303
304 pub struct IterMut<'a, T> {
306 _marker: PhantomData<&'a T>,
307 ptr: *mut T,
308 end: *mut T,
309 }
310
311 impl<'a, T> IterMut<'a, T> {
312 pub(crate) fn new(array: &'a Array<T>) -> Self {
313 let ptr = array.ptr;
314 Self {
315 _marker: PhantomData,
316 ptr,
317 end: unsafe { ptr.add(array.size) },
318 }
319 }
320 }
321
322 impl<'a, T> Iterator for IterMut<'a, T> {
323 type Item = &'a mut T;
324
325 fn next(&mut self) -> Option<Self::Item> {
326 if self.ptr == self.end {
327 None
328 } else {
329 unsafe {
330 let ptr = self.ptr;
331 self.ptr = self.ptr.add(1);
332 Some(&mut *ptr)
333 }
334 }
335 }
336 }
337
338 pub struct IntoIter<T> {
340 _array: Array<T>,
341 ptr: *const T,
342 end: *const T,
343 }
344
345 impl<T> IntoIter<T> {
346 pub(crate) fn new(array: Array<T>) -> Self {
347 unsafe {
348 let ptr = array.ptr.cast_const();
349 let end = ptr.add(array.size);
350 Self {
351 _array: array,
352 ptr,
353 end,
354 }
355 }
356 }
357 }
358
359 impl<T> Iterator for IntoIter<T> {
360 type Item = T;
361
362 fn next(&mut self) -> Option<Self::Item> {
363 if self.ptr == self.end {
364 None
365 } else {
366 unsafe {
367 let ptr = self.ptr;
368 self.ptr = self.ptr.add(1);
369 Some(ptr.read())
370 }
371 }
372 }
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn array_basics() {
382 let mut array = Array::new(5).expect("failed to allocate");
383 array[0] = 1;
384 array[1] = 2;
385 array[2] = 3;
386 array[3] = 4;
387 array[4] = 5;
388
389 for (i, v) in array.iter().enumerate() {
390 match i {
391 0 => assert_eq!(*v, 1),
392 1 => assert_eq!(*v, 2),
393 2 => assert_eq!(*v, 3),
394 3 => assert_eq!(*v, 4),
395 4 => assert_eq!(*v, 5),
396 _ => unreachable!(),
397 }
398 }
399 }
400}