Add [T; N]::each_ref
and [T; N]::each_mut
These methods work very similarly to `Option`'s methods `as_ref` and `as_mut`. They are useful in several situation, particularly when calling other array methods (like `map`) on the result. Unfortunately, we can't easily call them `as_ref` and `as_mut` as that would shadow those methods on slices, thus being a breaking change (that is likely to affect a lot of code).
This commit is contained in:
parent
a2cd91ceb0
commit
4038042eb0
1 changed files with 72 additions and 3 deletions
|
@ -12,6 +12,7 @@ use crate::convert::{Infallible, TryFrom};
|
|||
use crate::fmt;
|
||||
use crate::hash::{self, Hash};
|
||||
use crate::marker::Unsize;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::ops::{Index, IndexMut};
|
||||
use crate::slice::{Iter, IterMut};
|
||||
|
||||
|
@ -429,7 +430,6 @@ impl<T, const N: usize> [T; N] {
|
|||
where
|
||||
F: FnMut(T) -> U,
|
||||
{
|
||||
use crate::mem::MaybeUninit;
|
||||
struct Guard<T, const N: usize> {
|
||||
dst: *mut T,
|
||||
initialized: usize,
|
||||
|
@ -481,8 +481,6 @@ impl<T, const N: usize> [T; N] {
|
|||
/// ```
|
||||
#[unstable(feature = "array_zip", issue = "80094")]
|
||||
pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
|
||||
use crate::mem::MaybeUninit;
|
||||
|
||||
let mut dst = MaybeUninit::uninit_array::<N>();
|
||||
for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() {
|
||||
dst[i].write((lhs, rhs));
|
||||
|
@ -506,4 +504,75 @@ impl<T, const N: usize> [T; N] {
|
|||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
|
||||
/// Borrows each element and returns an array of references with the same
|
||||
/// size as `self`.
|
||||
///
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods)]
|
||||
///
|
||||
/// let floats = [3.1, 2.7, -1.0];
|
||||
/// let float_refs: [&f64; 3] = floats.each_ref();
|
||||
/// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
|
||||
/// ```
|
||||
///
|
||||
/// This method is particularly useful if combined with other methods, like
|
||||
/// [`map`](#method.map). This way, you can can avoid moving the original
|
||||
/// array if its elements are not `Copy`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods, array_map)]
|
||||
///
|
||||
/// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
|
||||
/// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
|
||||
/// assert_eq!(is_ascii, [true, false, true]);
|
||||
///
|
||||
/// // We can still access the original array: it has not been moved.
|
||||
/// assert_eq!(strings.len(), 3);
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn each_ref(&self) -> [&T; N] {
|
||||
// Unlike in `map`, we don't need a guard here, as dropping a reference
|
||||
// is a noop.
|
||||
let mut out = MaybeUninit::uninit_array::<N>();
|
||||
for (src, dst) in self.iter().zip(&mut out) {
|
||||
dst.write(src);
|
||||
}
|
||||
|
||||
// SAFETY: All elements of `dst` are properly initialized and
|
||||
// `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
|
||||
unsafe { (&mut out as *mut _ as *mut [&T; N]).read() }
|
||||
}
|
||||
|
||||
/// Borrows each element mutably and returns an array of mutable references
|
||||
/// with the same size as `self`.
|
||||
///
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods)]
|
||||
///
|
||||
/// let mut floats = [3.1, 2.7, -1.0];
|
||||
/// let float_refs: [&mut f64; 3] = floats.each_mut();
|
||||
/// *float_refs[0] = 0.0;
|
||||
/// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
|
||||
/// assert_eq!(floats, [0.0, 2.7, -1.0]);
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn each_mut(&mut self) -> [&mut T; N] {
|
||||
// Unlike in `map`, we don't need a guard here, as dropping a reference
|
||||
// is a noop.
|
||||
let mut out = MaybeUninit::uninit_array::<N>();
|
||||
for (src, dst) in self.iter_mut().zip(&mut out) {
|
||||
dst.write(src);
|
||||
}
|
||||
|
||||
// SAFETY: All elements of `dst` are properly initialized and
|
||||
// `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
|
||||
unsafe { (&mut out as *mut _ as *mut [&mut T; N]).read() }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue