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