Skip to main content

xtk_core/
array.rs

1#![expect(
2    unsafe_op_in_unsafe_fn,
3    reason = "Array requires unsafe code in some places"
4)]
5
6//! Variable length heap array
7
8use core::ops::{Deref, DerefMut, Index, IndexMut};
9use std::alloc;
10
11/// Variable length array.
12///
13/// The purpose of this data structure is to provide an alternative to [Vec] with a static length.
14/// Use a normal array if you know the length at compile time.
15///
16/// A possible use for [Array] is where you need to read from a [std::io::Read]er to a [Vec] using
17/// the [std::io::Read::read] function, this wouldn't work because some elements of a [Vec] may be
18/// uninitialized whereas [Array] functions just like a static compile-time known array.
19///
20/// # Examples
21///
22/// ```
23/// use xtk_core::array::Array;
24///
25/// let mut array = Array::new(5);
26///
27/// array[0] = 1;
28/// array[1] = 2;
29/// array[2] = 3;
30/// array[3] = 4;
31/// array[4] = 5;
32/// ```
33pub struct Array<T> {
34    ptr: *mut T,
35    size: usize,
36    layout: alloc::Layout,
37}
38
39impl<T> Array<T> {
40    /// Allocate an [Array]
41    ///
42    ///
43    /// # Examples
44    /// ```
45    /// use xtk_core::array::Array;
46    ///
47    /// let mut array = Array::new(10);
48    ///
49    /// array[0] = 1;
50    /// ```
51    #[must_use]
52    pub fn new(size: usize) -> Self {
53        unsafe {
54            let layout = alloc::Layout::array::<T>(size).expect("layout creation failed");
55            let ptr = alloc::alloc(layout) as *mut T;
56
57            assert!(!ptr.is_null(), "array allocation failed");
58
59            Self { ptr, size, layout }
60        }
61    }
62
63    /// Get the size of the array
64    #[must_use]
65    #[doc(alias = "len")]
66    pub const fn size(&self) -> usize {
67        self.size
68    }
69
70    /// Return the array as an immutable pointer
71    #[must_use]
72    pub const fn as_ptr(&self) -> *const T {
73        self.ptr
74    }
75
76    /// Return the array as a mutable pointer
77    #[must_use]
78    pub const fn as_mut_ptr(&self) -> *mut T {
79        self.ptr
80    }
81
82    /// Set value at `index` to `value`
83    ///
84    /// # Panics
85    ///
86    /// Panics when `index` is out of bounds
87    pub fn set(&mut self, index: usize, value: T) {
88        if index >= self.size {
89            panic!("index out of bounds");
90        }
91
92        // SAFETY: it is ensured that whatever this pointer points to is inside of the array by
93        // the previous statement
94        unsafe { *(self.ptr.add(index)) = value }
95    }
96
97    /// Get value at index `index`
98    #[must_use]
99    pub const fn get(&self, index: usize) -> Option<&T> {
100        if index >= self.size {
101            return None;
102        }
103
104        // SAFETY: it is ensured that whatever this pointer points to is inside of the `Array` by
105        // the previous statement
106        unsafe { Some(&(*(self.ptr.add(index)))) }
107    }
108
109    /// Get value at index `index`
110    #[must_use]
111    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
112        if index >= self.size {
113            return None;
114        }
115
116        // SAFETY: it is ensured that whatever this pointer points to is inside of the `Array` by
117        // the previous statement
118        unsafe { Some(&mut (*(self.ptr.add(index)))) }
119    }
120
121    /// Returns an immutable pointer to value at `index`.
122    ///
123    /// # Safety
124    ///
125    /// The pointer is obtained using unchecked pointer arithmetic.
126    #[must_use]
127    pub const unsafe fn get_ptr(&self, index: usize) -> *const T {
128        self.ptr.add(index) as *const T
129    }
130
131    /// Returns a mutable pointer to value at `index`.
132    ///
133    /// # Safety
134    ///
135    /// The pointer is obtained using unchecked pointer arithmetic.
136    #[must_use]
137    pub const unsafe fn get_ptr_mut(&mut self, index: usize) -> *mut T {
138        self.ptr.add(index)
139    }
140
141    /// Return an iterator over the array
142    #[must_use]
143    pub fn iter(&self) -> iter::Iter<'_, T> {
144        iter::Iter::new(self)
145    }
146
147    /// Return a mutable iterator over the array
148    #[must_use]
149    pub fn iter_mut(&mut self) -> iter::IterMut<'_, T> {
150        iter::IterMut::new(self)
151    }
152}
153
154impl<T: Clone> Array<T> {
155    /// Fill array with elements of `slice` by cloning the elements
156    pub fn fill(&mut self, slice: &[T]) {
157        for (i, t) in slice.iter().enumerate() {
158            if i >= self.size {
159                break;
160            }
161            self[i] = t.clone();
162        }
163    }
164
165    /// Allocates a new array with `n` extra length, clones all elements of the array into the new
166    /// one, hence `T` must implement [Clone].
167    ///
168    /// All elements of the array starting from [Array::size] + `n` will be uninitialized.
169    ///
170    /// # Panics
171    ///
172    /// This function will panic if the reallocation of the underlying data fails.
173    pub fn grow(&mut self, n: usize) {
174        let new_size = self.size() + n;
175
176        unsafe {
177            self.ptr = alloc::realloc(self.ptr as _, self.layout, new_size) as _;
178
179            if self.ptr.is_null() {
180                panic!("Reallocation failed");
181            }
182        }
183
184        self.size = new_size;
185    }
186
187    /// Create a new [Array] of length `n`
188    ///
189    /// `n` should not be less than the length of the array.
190    pub fn resized(&self, n: usize) -> Array<T> {
191        let new_size = self.size() + n;
192
193        let mut a = Array::new(new_size);
194
195        for i in 0..new_size {
196            a[i] = self.get(i).cloned().unwrap();
197        }
198
199        a
200    }
201}
202
203impl<T> Drop for Array<T> {
204    fn drop(&mut self) {
205        unsafe {
206            self.ptr.drop_in_place();
207            alloc::dealloc(self.ptr as *mut u8, self.layout);
208        }
209    }
210}
211
212impl<T> Deref for Array<T> {
213    type Target = [T];
214
215    fn deref(&self) -> &Self::Target {
216        // SAFETY: the length is known in the struct so this wont result in UB
217        unsafe { core::slice::from_raw_parts(self.ptr, self.size) }
218    }
219}
220
221impl<T> DerefMut for Array<T> {
222    fn deref_mut(&mut self) -> &mut Self::Target {
223        // SAFETY: the length is known in the struct so this wont result in UB
224        unsafe { core::slice::from_raw_parts_mut(self.ptr, self.size) }
225    }
226}
227
228impl<T> AsRef<[T]> for Array<T> {
229    fn as_ref(&self) -> &[T] {
230        self
231    }
232}
233
234impl<T> AsMut<[T]> for Array<T> {
235    fn as_mut(&mut self) -> &mut [T] {
236        self
237    }
238}
239
240impl<T> From<Vec<T>> for Array<T> {
241    fn from(mut value: Vec<T>) -> Self {
242        let mut v = Self::new(value.len());
243        v.swap_with_slice(&mut value);
244        v
245    }
246}
247
248/// [std::io::Write] is implemented for any [`Array<u8>`]
249impl std::io::Write for Array<u8> {
250    // TODO: is this implementation even good?
251    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
252        let start = self.ptr;
253
254        unsafe {
255            for i in 0..self.size {
256                if i > buf.len() {
257                    break;
258                }
259                *self.ptr = buf[i];
260                self.ptr = self.ptr.add(1);
261            }
262        }
263        self.ptr = start;
264
265        Ok(buf.len())
266    }
267
268    fn flush(&mut self) -> std::io::Result<()> {
269        Ok(())
270    }
271}
272
273impl<T> Index<usize> for Array<T> {
274    type Output = T;
275
276    fn index(&self, index: usize) -> &Self::Output {
277        self.get(index).expect("index out of bounds")
278    }
279}
280
281impl<T> IndexMut<usize> for Array<T> {
282    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
283        self.get_mut(index).expect("index out of bounds")
284    }
285}
286
287impl<T: Clone> Clone for Array<T> {
288    fn clone(&self) -> Self {
289        let mut array = Array::new(self.size);
290
291        for (i, v) in self.iter().enumerate() {
292            array[i] = v.clone();
293        }
294
295        array
296    }
297}
298
299impl<T> IntoIterator for Array<T> {
300    type Item = T;
301    type IntoIter = iter::IntoIter<T>;
302
303    fn into_iter(self) -> Self::IntoIter {
304        iter::IntoIter::new(self)
305    }
306}
307
308impl<'a, T> IntoIterator for &'a Array<T> {
309    type Item = &'a T;
310    type IntoIter = iter::Iter<'a, T>;
311
312    fn into_iter(self) -> Self::IntoIter {
313        self.iter()
314    }
315}
316
317impl<'a, T> IntoIterator for &'a mut Array<T> {
318    type Item = &'a mut T;
319    type IntoIter = iter::IterMut<'a, T>;
320
321    fn into_iter(self) -> Self::IntoIter {
322        self.iter_mut()
323    }
324}
325
326#[cfg(feature = "serde")]
327impl<T: serde::Serialize> serde::Serialize for Array<T> {
328    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
329    where
330        S: serde::Serializer,
331    {
332        (&self).serialize(serializer)
333    }
334}
335
336#[cfg(feature = "serde")]
337impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Array<T> {
338    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
339    where
340        D: serde::Deserializer<'de>,
341    {
342        let v = Vec::<T>::deserialize(deserializer)?;
343        Ok(Array::<T>::from(v))
344    }
345}
346
347/// Iterators for [Array]
348pub mod iter {
349    use super::Array;
350    use core::marker::PhantomData;
351
352    /// Immutable [Array] iterator.
353    pub struct Iter<'a, T> {
354        _marker: PhantomData<&'a T>,
355        ptr: *const T,
356        end: *const T,
357    }
358
359    impl<'a, T> Iter<'a, T> {
360        pub(crate) fn new(array: &'a Array<T>) -> Self {
361            let ptr = array.ptr;
362            Self {
363                _marker: PhantomData,
364                ptr,
365                end: unsafe { ptr.add(array.size) },
366            }
367        }
368    }
369
370    impl<'a, T> Iterator for Iter<'a, T> {
371        type Item = &'a T;
372
373        fn next(&mut self) -> Option<Self::Item> {
374            if self.ptr == self.end {
375                None
376            } else {
377                unsafe {
378                    let ptr = self.ptr;
379                    self.ptr = self.ptr.add(1);
380                    Some(&*ptr)
381                }
382            }
383        }
384    }
385
386    /// Mutable [Array] iterator
387    pub struct IterMut<'a, T> {
388        _marker: PhantomData<&'a T>,
389        ptr: *mut T,
390        end: *mut T,
391    }
392
393    impl<'a, T> IterMut<'a, T> {
394        pub(crate) fn new(array: &'a Array<T>) -> Self {
395            let ptr = array.ptr;
396            Self {
397                _marker: PhantomData,
398                ptr,
399                end: unsafe { ptr.add(array.size) },
400            }
401        }
402    }
403
404    impl<'a, T> Iterator for IterMut<'a, T> {
405        type Item = &'a mut T;
406
407        fn next(&mut self) -> Option<Self::Item> {
408            if self.ptr == self.end {
409                None
410            } else {
411                unsafe {
412                    let ptr = self.ptr;
413                    self.ptr = self.ptr.add(1);
414                    Some(&mut *ptr)
415                }
416            }
417        }
418    }
419
420    /// Owned [Array] Iterator
421    pub struct IntoIter<T> {
422        _array: Array<T>,
423        ptr: *const T,
424        end: *const T,
425    }
426
427    impl<T> IntoIter<T> {
428        pub(crate) fn new(array: Array<T>) -> Self {
429            unsafe {
430                let ptr = array.ptr.cast_const();
431                let end = ptr.add(array.size);
432                Self {
433                    _array: array,
434                    ptr,
435                    end,
436                }
437            }
438        }
439    }
440
441    impl<T> Iterator for IntoIter<T> {
442        type Item = T;
443
444        fn next(&mut self) -> Option<Self::Item> {
445            if self.ptr == self.end {
446                None
447            } else {
448                unsafe {
449                    let ptr = self.ptr;
450                    self.ptr = self.ptr.add(1);
451                    Some(ptr.read())
452                }
453            }
454        }
455    }
456}
457
458#[cfg(test)]
459mod tests {
460    use std::io::Read;
461
462    use super::*;
463
464    #[test]
465    fn index_and_iter() {
466        let mut array = Array::new(5);
467
468        array[0] = 1;
469        array[1] = 2;
470        array[2] = 3;
471        array[3] = 4;
472        array[4] = 5;
473
474        for (i, v) in array.iter().enumerate() {
475            assert_eq!(*v, i + 1);
476        }
477    }
478
479    #[test]
480    fn len() {
481        let array: Array<()> = Array::new(15);
482
483        assert_eq!(array.size(), 15);
484    }
485
486    #[test]
487    fn grow() {
488        let mut array: Array<i32> = Array::new(5);
489
490        array[0] = 1;
491        array[1] = 2;
492        array[2] = 3;
493
494        assert_eq!(array.size(), 5);
495        array.grow(30);
496        assert_eq!(array.size(), 35);
497
498        assert_eq!(array[1], 2);
499    }
500
501    #[test]
502    fn writer() {
503        let array = {
504            let mut a = Array::<u8>::new(12);
505            a.fill(b"Hello world!");
506            a
507        };
508
509        let mut cursor = std::io::Cursor::new(array);
510
511        let mut buf = [0u8; 5];
512        let read = cursor.read(&mut buf).unwrap();
513        assert!(read == 5);
514        let s = str::from_utf8(&buf).unwrap();
515        println!("{}", s);
516    }
517}