diff options
| author | kadmin <julianknodt@gmail.com> | 2020-08-06 07:40:06 +0000 |
|---|---|---|
| committer | kadmin <julianknodt@gmail.com> | 2020-08-13 03:50:54 +0000 |
| commit | d8718183b2f3e0dacc2731b5c84fe7b0eb197a6e (patch) | |
| tree | 5188a0e89a085a23298982cf7067b8115e6c36dd /library/core/src/array | |
| parent | 847ba835ce411d47364a93ddf0b4a5c0f27928a9 (diff) | |
| download | rust-d8718183b2f3e0dacc2731b5c84fe7b0eb197a6e.tar.gz rust-d8718183b2f3e0dacc2731b5c84fe7b0eb197a6e.zip | |
Create lang item array and add map fn
This creates the language item for arrays, and adds the map fn which is like map in options or iterators. It currently allocates an extra array, unfortunately. Added fixme for transmuting Fix typo Add drop guard
Diffstat (limited to 'library/core/src/array')
| -rw-r--r-- | library/core/src/array/mod.rs | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index c0bf3833b9c..b549cd8959f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -364,3 +364,56 @@ macro_rules! array_impl_default { } array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T} + +#[cfg(not(bootstrap))] +#[lang = "array"] +impl<T, const N: usize> [T; N] { + /// Returns an array of the same size as self, with `f` applied to each element. + /// + /// # Examples + /// ``` + /// let x = [1,2,3]; + /// let y = x.map(|v| v + 1); + /// assert_eq!(y, [2,3,4]); + /// ``` + #[unstable(feature = "array_map", issue = "77777")] + fn map<F, S>(self, f: F) -> [S; N] + where + F: FnMut(T) -> S, + { + use crate::mem::MaybeUninit; + struct Guard<T, const N: usize> { + dst: *mut T, + curr_init: usize, + } + + impl<T, const N: usize> Guard<T, N> { + fn new(dst: &mut [MaybeUninit<T>; N]) -> Self { + Guard { dst: dst as *mut _ as *mut T, curr_init: 0 } + } + } + + impl<T, const N: usize> Drop for Guard<T, N> { + fn drop(&mut self) { + debug_assert!(self.curr_init <= N); + + let initialized_part = + crate::ptr::slice_from_raw_parts_mut(self.dst, self.curr_init); + // SAFETY: this raw slice will contain only initialized objects + // that's why, it is allowed to drop it. + unsafe { + crate::ptr::drop_in_place(initialized_part); + } + } + } + let dst = MaybeUninit::uninit_array::<N>(); + let mut guard = Guard::new(&mut dst); + for (i, e) in self.into_iter().enumerate() { + dst[i] = MaybeUninit::new(f(e)); + guard.curr_init += 1; + } + // FIXME convert to crate::mem::transmute when works with generics + // unsafe { crate::mem::transmute::<[MaybeUninit<S>; N], [S; N]>(dst) } + unsafe { (&mut dst as *mut _ as *mut [S; N]).read() } + } +} |
