|
202 | 202 | use crate::{
|
203 | 203 | error::{self, Error},
|
204 | 204 | sync::UniqueArc,
|
| 205 | + types::ScopeGuard, |
205 | 206 | };
|
206 | 207 | use alloc::boxed::Box;
|
207 | 208 | use core::{
|
@@ -867,6 +868,93 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
|
867 | 868 | unsafe { init_from_closure(|_| Ok(())) }
|
868 | 869 | }
|
869 | 870 |
|
| 871 | +/// Initializes an array by initializing each element via the provided initializer. |
| 872 | +/// |
| 873 | +/// # Examples |
| 874 | +/// |
| 875 | +/// ```rust |
| 876 | +/// use kernel::{error::Error, init::init_array_from_fn}; |
| 877 | +/// let array: Box<[usize; 1_000]>= Box::init::<Error>(init_array_from_fn(|i| i)).unwrap(); |
| 878 | +/// assert_eq!(array.len(), 1_000); |
| 879 | +/// ``` |
| 880 | +pub fn init_array_from_fn<I, const N: usize, T, E>( |
| 881 | + mut make_init: impl FnMut(usize) -> I, |
| 882 | +) -> impl Init<[T; N], E> |
| 883 | +where |
| 884 | + I: Init<T, E>, |
| 885 | +{ |
| 886 | + let init = move |slot: *mut [T; N]| { |
| 887 | + let slot = slot.cast::<T>(); |
| 888 | + // Counts the number of initialized elements and when dropped drops that many elements from |
| 889 | + // `slot`. |
| 890 | + let mut init_count = ScopeGuard::new_with_data(0, |i| { |
| 891 | + // We now free every element that has been initialized before: |
| 892 | + // SAFETY: The loop initialized exactly the values from 0..i and since we |
| 893 | + // return `Err` below, the caller will consider the memory at `slot` as |
| 894 | + // uninitialized. |
| 895 | + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; |
| 896 | + }); |
| 897 | + for i in 0..N { |
| 898 | + let init = make_init(i); |
| 899 | + // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. |
| 900 | + let ptr = unsafe { slot.add(i) }; |
| 901 | + // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` |
| 902 | + // requirements. |
| 903 | + unsafe { init.__init(ptr) }?; |
| 904 | + *init_count += 1; |
| 905 | + } |
| 906 | + init_count.dismiss(); |
| 907 | + Ok(()) |
| 908 | + }; |
| 909 | + // SAFETY: The initializer above initializes every element of the array. On failure it drops |
| 910 | + // any initialized elements and returns `Err`. |
| 911 | + unsafe { init_from_closure(init) } |
| 912 | +} |
| 913 | + |
| 914 | +/// Initializes an array by initializing each element via the provided initializer. |
| 915 | +/// |
| 916 | +/// # Examples |
| 917 | +/// |
| 918 | +/// ```rust |
| 919 | +/// use kernel::{sync::{Arc, Mutex}, init::pin_init_array_from_fn, new_mutex}; |
| 920 | +/// let array: Arc<[Mutex<usize>; 1_000]>= |
| 921 | +/// Arc::pin_init(pin_init_array_from_fn(|i| new_mutex!(i))).unwrap(); |
| 922 | +/// assert_eq!(array.len(), 1_000); |
| 923 | +/// ``` |
| 924 | +pub fn pin_init_array_from_fn<I, const N: usize, T, E>( |
| 925 | + mut make_init: impl FnMut(usize) -> I, |
| 926 | +) -> impl PinInit<[T; N], E> |
| 927 | +where |
| 928 | + I: PinInit<T, E>, |
| 929 | +{ |
| 930 | + let init = move |slot: *mut [T; N]| { |
| 931 | + let slot = slot.cast::<T>(); |
| 932 | + // Counts the number of initialized elements and when dropped drops that many elements from |
| 933 | + // `slot`. |
| 934 | + let mut init_count = ScopeGuard::new_with_data(0, |i| { |
| 935 | + // We now free every element that has been initialized before: |
| 936 | + // SAFETY: The loop initialized exactly the values from 0..i and since we |
| 937 | + // return `Err` below, the caller will consider the memory at `slot` as |
| 938 | + // uninitialized. |
| 939 | + unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) }; |
| 940 | + }); |
| 941 | + for i in 0..N { |
| 942 | + let init = make_init(i); |
| 943 | + // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`. |
| 944 | + let ptr = unsafe { slot.add(i) }; |
| 945 | + // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init` |
| 946 | + // requirements. |
| 947 | + unsafe { init.__pinned_init(ptr) }?; |
| 948 | + *init_count += 1; |
| 949 | + } |
| 950 | + init_count.dismiss(); |
| 951 | + Ok(()) |
| 952 | + }; |
| 953 | + // SAFETY: The initializer above initializes every element of the array. On failure it drops |
| 954 | + // any initialized elements and returns `Err`. |
| 955 | + unsafe { pin_init_from_closure(init) } |
| 956 | +} |
| 957 | + |
870 | 958 | // SAFETY: Every type can be initialized by-value.
|
871 | 959 | unsafe impl<T, E> Init<T, E> for T {
|
872 | 960 | unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
|
|
0 commit comments