Skip to content

Commit 79ef369

Browse files
committed
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
1 parent 5ae5916 commit 79ef369

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

core/src/array/mod.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,56 @@ macro_rules! array_impl_default {
364364
}
365365

366366
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}
367+
368+
#[cfg(not(bootstrap))]
369+
#[lang = "array"]
370+
impl<T, const N: usize> [T; N] {
371+
/// Returns an array of the same size as self, with `f` applied to each element.
372+
///
373+
/// # Examples
374+
/// ```
375+
/// let x = [1,2,3];
376+
/// let y = x.map(|v| v + 1);
377+
/// assert_eq!(y, [2,3,4]);
378+
/// ```
379+
#[unstable(feature = "array_map", issue = "77777")]
380+
fn map<F, S>(self, f: F) -> [S; N]
381+
where
382+
F: FnMut(T) -> S,
383+
{
384+
use crate::mem::MaybeUninit;
385+
struct Guard<T, const N: usize> {
386+
dst: *mut T,
387+
curr_init: usize,
388+
}
389+
390+
impl<T, const N: usize> Guard<T, N> {
391+
fn new(dst: &mut [MaybeUninit<T>; N]) -> Self {
392+
Guard { dst: dst as *mut _ as *mut T, curr_init: 0 }
393+
}
394+
}
395+
396+
impl<T, const N: usize> Drop for Guard<T, N> {
397+
fn drop(&mut self) {
398+
debug_assert!(self.curr_init <= N);
399+
400+
let initialized_part =
401+
crate::ptr::slice_from_raw_parts_mut(self.dst, self.curr_init);
402+
// SAFETY: this raw slice will contain only initialized objects
403+
// that's why, it is allowed to drop it.
404+
unsafe {
405+
crate::ptr::drop_in_place(initialized_part);
406+
}
407+
}
408+
}
409+
let dst = MaybeUninit::uninit_array::<N>();
410+
let mut guard = Guard::new(&mut dst);
411+
for (i, e) in self.into_iter().enumerate() {
412+
dst[i] = MaybeUninit::new(f(e));
413+
guard.curr_init += 1;
414+
}
415+
// FIXME convert to crate::mem::transmute when works with generics
416+
// unsafe { crate::mem::transmute::<[MaybeUninit<S>; N], [S; N]>(dst) }
417+
unsafe { (&mut dst as *mut _ as *mut [S; N]).read() }
418+
}
419+
}

0 commit comments

Comments
 (0)