@@ -12,6 +12,7 @@ use crate::convert::{Infallible, TryFrom};
12
12
use crate :: fmt;
13
13
use crate :: hash:: { self , Hash } ;
14
14
use crate :: marker:: Unsize ;
15
+ use crate :: mem:: MaybeUninit ;
15
16
use crate :: ops:: { Index , IndexMut } ;
16
17
use crate :: slice:: { Iter , IterMut } ;
17
18
@@ -429,7 +430,6 @@ impl<T, const N: usize> [T; N] {
429
430
where
430
431
F : FnMut ( T ) -> U ,
431
432
{
432
- use crate :: mem:: MaybeUninit ;
433
433
struct Guard < T , const N : usize > {
434
434
dst : * mut T ,
435
435
initialized : usize ,
@@ -481,8 +481,6 @@ impl<T, const N: usize> [T; N] {
481
481
/// ```
482
482
#[ unstable( feature = "array_zip" , issue = "80094" ) ]
483
483
pub fn zip < U > ( self , rhs : [ U ; N ] ) -> [ ( T , U ) ; N ] {
484
- use crate :: mem:: MaybeUninit ;
485
-
486
484
let mut dst = MaybeUninit :: uninit_array :: < N > ( ) ;
487
485
for ( i, ( lhs, rhs) ) in IntoIter :: new ( self ) . zip ( IntoIter :: new ( rhs) ) . enumerate ( ) {
488
486
dst[ i] . write ( ( lhs, rhs) ) ;
@@ -506,4 +504,75 @@ impl<T, const N: usize> [T; N] {
506
504
pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
507
505
self
508
506
}
507
+
508
+ /// Borrows each element and returns an array of references with the same
509
+ /// size as `self`.
510
+ ///
511
+ ///
512
+ /// # Example
513
+ ///
514
+ /// ```
515
+ /// #![feature(array_methods)]
516
+ ///
517
+ /// let floats = [3.1, 2.7, -1.0];
518
+ /// let float_refs: [&f64; 3] = floats.each_ref();
519
+ /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
520
+ /// ```
521
+ ///
522
+ /// This method is particularly useful if combined with other methods, like
523
+ /// [`map`](#method.map). This way, you can can avoid moving the original
524
+ /// array if its elements are not `Copy`.
525
+ ///
526
+ /// ```
527
+ /// #![feature(array_methods, array_map)]
528
+ ///
529
+ /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
530
+ /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
531
+ /// assert_eq!(is_ascii, [true, false, true]);
532
+ ///
533
+ /// // We can still access the original array: it has not been moved.
534
+ /// assert_eq!(strings.len(), 3);
535
+ /// ```
536
+ #[ unstable( feature = "array_methods" , issue = "76118" ) ]
537
+ pub fn each_ref ( & self ) -> [ & T ; N ] {
538
+ // Unlike in `map`, we don't need a guard here, as dropping a reference
539
+ // is a noop.
540
+ let mut out = MaybeUninit :: uninit_array :: < N > ( ) ;
541
+ for ( src, dst) in self . iter ( ) . zip ( & mut out) {
542
+ dst. write ( src) ;
543
+ }
544
+
545
+ // SAFETY: All elements of `dst` are properly initialized and
546
+ // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
547
+ unsafe { ( & mut out as * mut _ as * mut [ & T ; N ] ) . read ( ) }
548
+ }
549
+
550
+ /// Borrows each element mutably and returns an array of mutable references
551
+ /// with the same size as `self`.
552
+ ///
553
+ ///
554
+ /// # Example
555
+ ///
556
+ /// ```
557
+ /// #![feature(array_methods)]
558
+ ///
559
+ /// let mut floats = [3.1, 2.7, -1.0];
560
+ /// let float_refs: [&mut f64; 3] = floats.each_mut();
561
+ /// *float_refs[0] = 0.0;
562
+ /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
563
+ /// assert_eq!(floats, [0.0, 2.7, -1.0]);
564
+ /// ```
565
+ #[ unstable( feature = "array_methods" , issue = "76118" ) ]
566
+ pub fn each_mut ( & mut self ) -> [ & mut T ; N ] {
567
+ // Unlike in `map`, we don't need a guard here, as dropping a reference
568
+ // is a noop.
569
+ let mut out = MaybeUninit :: uninit_array :: < N > ( ) ;
570
+ for ( src, dst) in self . iter_mut ( ) . zip ( & mut out) {
571
+ dst. write ( src) ;
572
+ }
573
+
574
+ // SAFETY: All elements of `dst` are properly initialized and
575
+ // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
576
+ unsafe { ( & mut out as * mut _ as * mut [ & mut T ; N ] ) . read ( ) }
577
+ }
509
578
}
0 commit comments