heap_arr/lib.rs
1#![warn(clippy::pedantic)]
2#![no_std]
3
4use core::mem::{self, MaybeUninit};
5
6use alloc::{
7 alloc::{handle_alloc_error, Layout, LayoutError},
8 boxed::Box,
9};
10
11extern crate alloc;
12
13/// Allocates `[T; N]` on the heap and initializes its entries to `initial`.
14///
15/// For now, this function uses the global allocator. This will change once the
16/// [`Allocator`](core::alloc::Allocator) trait becomes stable.
17///
18/// # Safety
19/// The result of this function is undefined if `mem::size_of::<T>() == 0`, or
20/// if `N == 0`
21///
22/// # Errors
23/// See [`Layout::array`]
24pub unsafe fn new<T, const N: usize>(initial: &T) -> Result<Box<[T; N]>, LayoutError>
25where
26 T: Clone,
27{
28 let mut arr = new_uninit::<T, N>()?;
29 for v in arr.as_mut() {
30 v.write(initial.clone());
31 }
32
33 Ok(mem::transmute(arr))
34}
35
36/// Allocates `[T; N]` on the heap and initializes its entries to `T::default()`.
37///
38/// For now, this function uses the global allocator. This will change once the
39/// [`Allocator`](core::alloc::Allocator) trait becomes stable.
40///
41/// # Safety
42/// The result of this function is undefined if `mem::size_of::<T>() == 0`, or
43/// if `N == 0`
44///
45/// # Errors
46/// See [`Layout::array`]
47pub unsafe fn new_default<T, const N: usize>() -> Result<Box<[T; N]>, LayoutError>
48where
49 T: Default,
50{
51 let mut arr = new_uninit::<T, N>()?;
52 for v in arr.as_mut() {
53 v.write(T::default());
54 }
55
56 Ok(mem::transmute(arr))
57}
58
59/// Allocates `[T; N]` on the heap.
60///
61/// For now, this function uses the global allocator. This will change once the
62/// [`Allocator`](core::alloc::Allocator) trait becomes stable.
63///
64/// # Safety
65/// The result of this function is undefined if `mem::size_of::<T>() == 0`, or
66/// if `N == 0`
67///
68/// # Errors
69/// See [`Layout::array`]
70///
71/// # Examples
72/// ```
73/// use std::mem;
74///
75/// unsafe {
76/// const LEN: usize = 1024 * 1024 * 1024;
77///
78/// let mut arr = heap_arr::new_uninit::<usize, LEN>().unwrap();
79/// for (i, v) in arr.as_mut().iter_mut().enumerate() {
80/// v.write(i);
81/// }
82///
83/// let arr: Box::<[usize; LEN]> = mem::transmute(arr);
84/// }
85/// ```
86pub unsafe fn new_uninit<T, const N: usize>() -> Result<Box<[MaybeUninit<T>; N]>, LayoutError> {
87 let layout = Layout::array::<T>(N)?;
88 let ptr = alloc::alloc::alloc(layout);
89
90 if ptr.is_null() {
91 handle_alloc_error(layout);
92 }
93 Ok(Box::from_raw(ptr.cast()))
94}
95
96#[cfg(test)]
97mod tests {
98 #[test]
99 fn test_new() {
100 let arr = unsafe { super::new::<Option<bool>, 1_000>(&Some(false)).unwrap() };
101 assert_eq!(arr.len(), 1_000);
102 assert_eq!(arr[999], Some(false));
103 }
104
105 #[test]
106 fn test_default() {
107 let arr = unsafe { super::new_default::<Option<bool>, 1_000>().unwrap() };
108 assert_eq!(arr.len(), 1_000);
109 assert_eq!(arr[999], None);
110 }
111
112 #[test]
113 fn test_uninit() {
114 let _ = unsafe { super::new_uninit::<u64, 1_000>().unwrap() };
115 }
116}