about summary refs log tree commit diff
path: root/library/core/src/array
diff options
context:
space:
mode:
authorkadmin <julianknodt@gmail.com>2020-08-06 07:40:06 +0000
committerkadmin <julianknodt@gmail.com>2020-08-13 03:50:54 +0000
commitd8718183b2f3e0dacc2731b5c84fe7b0eb197a6e (patch)
tree5188a0e89a085a23298982cf7067b8115e6c36dd /library/core/src/array
parent847ba835ce411d47364a93ddf0b4a5c0f27928a9 (diff)
downloadrust-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.rs53
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() }
+    }
+}