1
//! Utilities for the array primitive type.
2
//!
3
//! *[See also the array primitive type](array).*
4

            
5
#![stable(feature = "core_array", since = "1.35.0")]
6

            
7
#[cfg(not(feature = "ferrocene_certified"))]
8
use crate::borrow::{Borrow, BorrowMut};
9
#[cfg(not(feature = "ferrocene_certified"))]
10
use crate::cmp::Ordering;
11
#[cfg(not(feature = "ferrocene_certified"))]
12
use crate::convert::Infallible;
13
#[cfg(not(feature = "ferrocene_certified"))]
14
use crate::error::Error;
15
#[cfg(not(feature = "ferrocene_certified"))]
16
use crate::fmt;
17
#[cfg(not(feature = "ferrocene_certified"))]
18
use crate::hash::{self, Hash};
19
#[cfg(not(feature = "ferrocene_certified"))]
20
use crate::intrinsics::transmute_unchecked;
21
#[cfg(not(feature = "ferrocene_certified"))]
22
use crate::iter::{UncheckedIterator, repeat_n};
23
#[cfg(not(feature = "ferrocene_certified"))]
24
use crate::mem::{self, MaybeUninit};
25
#[cfg(not(feature = "ferrocene_certified"))]
26
use crate::ops::{
27
    ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
28
};
29
#[cfg(not(feature = "ferrocene_certified"))]
30
use crate::ptr::{null, null_mut};
31
#[cfg(not(feature = "ferrocene_certified"))]
32
use crate::slice::{Iter, IterMut};
33

            
34
#[cfg(not(feature = "ferrocene_certified"))]
35
mod ascii;
36
#[cfg(not(feature = "ferrocene_certified"))]
37
mod drain;
38
#[cfg(not(feature = "ferrocene_certified"))]
39
mod equality;
40
#[cfg(not(feature = "ferrocene_certified"))]
41
mod iter;
42

            
43
#[cfg(not(feature = "ferrocene_certified"))]
44
pub(crate) use drain::drain_array_with;
45
#[stable(feature = "array_value_iter", since = "1.51.0")]
46
// blocked by IntoIter
47
#[cfg(not(feature = "ferrocene_certified"))]
48
pub use iter::IntoIter;
49

            
50
/// Creates an array of type `[T; N]` by repeatedly cloning a value.
51
///
52
/// This is the same as `[val; N]`, but it also works for types that do not
53
/// implement [`Copy`].
54
///
55
/// The provided value will be used as an element of the resulting array and
56
/// will be cloned N - 1 times to fill up the rest. If N is zero, the value
57
/// will be dropped.
58
///
59
/// # Example
60
///
61
/// Creating multiple copies of a `String`:
62
/// ```rust
63
/// use std::array;
64
///
65
/// let string = "Hello there!".to_string();
66
/// let strings = array::repeat(string);
67
/// assert_eq!(strings, ["Hello there!", "Hello there!"]);
68
/// ```
69
#[inline]
70
#[must_use = "cloning is often expensive and is not expected to have side effects"]
71
#[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")]
72
#[cfg(not(feature = "ferrocene_certified"))]
73
pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
74
    from_trusted_iterator(repeat_n(val, N))
75
}
76

            
77
/// Creates an array where each element is produced by calling `f` with
78
/// that element's index while walking forward through the array.
79
///
80
/// This is essentially the same as writing
81
/// ```text
82
/// [f(0), f(1), f(2), …, f(N - 2), f(N - 1)]
83
/// ```
84
/// and is similar to `(0..i).map(f)`, just for arrays not iterators.
85
///
86
/// If `N == 0`, this produces an empty array without ever calling `f`.
87
///
88
/// # Example
89
///
90
/// ```rust
91
/// // type inference is helping us here, the way `from_fn` knows how many
92
/// // elements to produce is the length of array down there: only arrays of
93
/// // equal lengths can be compared, so the const generic parameter `N` is
94
/// // inferred to be 5, thus creating array of 5 elements.
95
///
96
/// let array = core::array::from_fn(|i| i);
97
/// // indexes are:    0  1  2  3  4
98
/// assert_eq!(array, [0, 1, 2, 3, 4]);
99
///
100
/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2);
101
/// // indexes are:     0  1  2  3  4  5   6   7
102
/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]);
103
///
104
/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0);
105
/// // indexes are:       0     1      2     3      4
106
/// assert_eq!(bool_arr, [true, false, true, false, true]);
107
/// ```
108
///
109
/// You can also capture things, for example to create an array full of clones
110
/// where you can't just use `[item; N]` because it's not `Copy`:
111
/// ```
112
/// # // TBH `array::repeat` would be better for this, but it's not stable yet.
113
/// let my_string = String::from("Hello");
114
/// let clones: [String; 42] = std::array::from_fn(|_| my_string.clone());
115
/// assert!(clones.iter().all(|x| *x == my_string));
116
/// ```
117
///
118
/// The array is generated in ascending index order, starting from the front
119
/// and going towards the back, so you can use closures with mutable state:
120
/// ```
121
/// let mut state = 1;
122
/// let a = std::array::from_fn(|_| { let x = state; state *= 2; x });
123
/// assert_eq!(a, [1, 2, 4, 8, 16, 32]);
124
/// ```
125
#[inline]
126
#[stable(feature = "array_from_fn", since = "1.63.0")]
127
#[cfg(not(feature = "ferrocene_certified"))]
128
pub fn from_fn<T, const N: usize, F>(f: F) -> [T; N]
129
where
130
    F: FnMut(usize) -> T,
131
{
132
    try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0
133
}
134

            
135
/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
136
/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
137
/// if any element creation was unsuccessful.
138
///
139
/// The return type of this function depends on the return type of the closure.
140
/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
141
/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
142
///
143
/// # Arguments
144
///
145
/// * `cb`: Callback where the passed argument is the current array index.
146
///
147
/// # Example
148
///
149
/// ```rust
150
/// #![feature(array_try_from_fn)]
151
///
152
/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into());
153
/// assert_eq!(array, Ok([0, 1, 2, 3, 4]));
154
///
155
/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into());
156
/// assert!(array.is_err());
157
///
158
/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100));
159
/// assert_eq!(array, Some([100, 101, 102, 103]));
160
///
161
/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100));
162
/// assert_eq!(array, None);
163
/// ```
164
#[inline]
165
#[unstable(feature = "array_try_from_fn", issue = "89379")]
166
#[cfg(not(feature = "ferrocene_certified"))]
167
pub fn try_from_fn<R, const N: usize, F>(cb: F) -> ChangeOutputType<R, [R::Output; N]>
168
where
169
    F: FnMut(usize) -> R,
170
    R: Try,
171
    R::Residual: Residual<[R::Output; N]>,
172
{
173
    let mut array = [const { MaybeUninit::uninit() }; N];
174
    match try_from_fn_erased(&mut array, cb) {
175
        ControlFlow::Break(r) => FromResidual::from_residual(r),
176
        ControlFlow::Continue(()) => {
177
            // SAFETY: All elements of the array were populated.
178
            try { unsafe { MaybeUninit::array_assume_init(array) } }
179
        }
180
    }
181
}
182

            
183
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
184
#[stable(feature = "array_from_ref", since = "1.53.0")]
185
#[rustc_const_stable(feature = "const_array_from_ref_shared", since = "1.63.0")]
186
#[cfg(not(feature = "ferrocene_certified"))]
187
pub const fn from_ref<T>(s: &T) -> &[T; 1] {
188
    // SAFETY: Converting `&T` to `&[T; 1]` is sound.
189
    unsafe { &*(s as *const T).cast::<[T; 1]>() }
190
}
191

            
192
/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying).
193
#[stable(feature = "array_from_ref", since = "1.53.0")]
194
#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")]
195
#[cfg(not(feature = "ferrocene_certified"))]
196
pub const fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
197
    // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound.
198
    unsafe { &mut *(s as *mut T).cast::<[T; 1]>() }
199
}
200

            
201
/// The error type returned when a conversion from a slice to an array fails.
202
#[stable(feature = "try_from", since = "1.34.0")]
203
#[derive(Debug, Copy, Clone)]
204
#[cfg(not(feature = "ferrocene_certified"))]
205
pub struct TryFromSliceError(());
206

            
207
#[stable(feature = "core_array", since = "1.35.0")]
208
#[cfg(not(feature = "ferrocene_certified"))]
209
impl fmt::Display for TryFromSliceError {
210
    #[inline]
211
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212
        "could not convert slice to array".fmt(f)
213
    }
214
}
215

            
216
#[stable(feature = "try_from", since = "1.34.0")]
217
#[cfg(not(feature = "ferrocene_certified"))]
218
impl Error for TryFromSliceError {}
219

            
220
#[stable(feature = "try_from_slice_error", since = "1.36.0")]
221
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
222
#[cfg(not(feature = "ferrocene_certified"))]
223
impl const From<Infallible> for TryFromSliceError {
224
    fn from(x: Infallible) -> TryFromSliceError {
225
        match x {}
226
    }
227
}
228

            
229
#[stable(feature = "rust1", since = "1.0.0")]
230
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
231
#[cfg(not(feature = "ferrocene_certified"))]
232
impl<T, const N: usize> const AsRef<[T]> for [T; N] {
233
    #[inline]
234
    fn as_ref(&self) -> &[T] {
235
        &self[..]
236
    }
237
}
238

            
239
#[stable(feature = "rust1", since = "1.0.0")]
240
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
241
#[cfg(not(feature = "ferrocene_certified"))]
242
impl<T, const N: usize> const AsMut<[T]> for [T; N] {
243
    #[inline]
244
    fn as_mut(&mut self) -> &mut [T] {
245
        &mut self[..]
246
    }
247
}
248

            
249
#[stable(feature = "array_borrow", since = "1.4.0")]
250
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
251
#[cfg(not(feature = "ferrocene_certified"))]
252
impl<T, const N: usize> const Borrow<[T]> for [T; N] {
253
    fn borrow(&self) -> &[T] {
254
        self
255
    }
256
}
257

            
258
#[stable(feature = "array_borrow", since = "1.4.0")]
259
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
260
#[cfg(not(feature = "ferrocene_certified"))]
261
impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
262
    fn borrow_mut(&mut self) -> &mut [T] {
263
        self
264
    }
265
}
266

            
267
/// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
268
/// Succeeds if `slice.len() == N`.
269
///
270
/// ```
271
/// let bytes: [u8; 3] = [1, 0, 2];
272
///
273
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
274
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
275
///
276
/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
277
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
278
/// ```
279
#[stable(feature = "try_from", since = "1.34.0")]
280
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
281
#[cfg(not(feature = "ferrocene_certified"))]
282
impl<T, const N: usize> const TryFrom<&[T]> for [T; N]
283
where
284
    T: Copy,
285
{
286
    type Error = TryFromSliceError;
287

            
288
    #[inline]
289
252
    fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
290
252
        <&Self>::try_from(slice).copied()
291
252
    }
292
}
293

            
294
/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
295
/// Succeeds if `slice.len() == N`.
296
///
297
/// ```
298
/// let mut bytes: [u8; 3] = [1, 0, 2];
299
///
300
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
301
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
302
///
303
/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
304
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
305
/// ```
306
#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
307
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
308
#[cfg(not(feature = "ferrocene_certified"))]
309
impl<T, const N: usize> const TryFrom<&mut [T]> for [T; N]
310
where
311
    T: Copy,
312
{
313
    type Error = TryFromSliceError;
314

            
315
    #[inline]
316
    fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
317
        <Self>::try_from(&*slice)
318
    }
319
}
320

            
321
/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
322
/// `slice.len() == N`.
323
///
324
/// ```
325
/// let bytes: [u8; 3] = [1, 0, 2];
326
///
327
/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
328
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
329
///
330
/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
331
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
332
/// ```
333
#[stable(feature = "try_from", since = "1.34.0")]
334
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
335
#[cfg(not(feature = "ferrocene_certified"))]
336
impl<'a, T, const N: usize> const TryFrom<&'a [T]> for &'a [T; N] {
337
    type Error = TryFromSliceError;
338

            
339
    #[inline]
340
252
    fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> {
341
252
        slice.as_array().ok_or(TryFromSliceError(()))
342
252
    }
343
}
344

            
345
/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
346
/// `&mut [T]`. Succeeds if `slice.len() == N`.
347
///
348
/// ```
349
/// let mut bytes: [u8; 3] = [1, 0, 2];
350
///
351
/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
352
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
353
///
354
/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
355
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
356
/// ```
357
#[stable(feature = "try_from", since = "1.34.0")]
358
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
359
#[cfg(not(feature = "ferrocene_certified"))]
360
impl<'a, T, const N: usize> const TryFrom<&'a mut [T]> for &'a mut [T; N] {
361
    type Error = TryFromSliceError;
362

            
363
    #[inline]
364
    fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> {
365
        slice.as_mut_array().ok_or(TryFromSliceError(()))
366
    }
367
}
368

            
369
/// The hash of an array is the same as that of the corresponding slice,
370
/// as required by the `Borrow` implementation.
371
///
372
/// ```
373
/// use std::hash::BuildHasher;
374
///
375
/// let b = std::hash::RandomState::new();
376
/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
377
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
378
/// assert_eq!(b.hash_one(a), b.hash_one(s));
379
/// ```
380
#[stable(feature = "rust1", since = "1.0.0")]
381
#[cfg(not(feature = "ferrocene_certified"))]
382
impl<T: Hash, const N: usize> Hash for [T; N] {
383
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
384
        Hash::hash(&self[..], state)
385
    }
386
}
387

            
388
#[stable(feature = "rust1", since = "1.0.0")]
389
#[cfg(not(feature = "ferrocene_certified"))]
390
impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
391
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392
        fmt::Debug::fmt(&&self[..], f)
393
    }
394
}
395

            
396
#[stable(feature = "rust1", since = "1.0.0")]
397
#[cfg(not(feature = "ferrocene_certified"))]
398
impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
399
    type Item = &'a T;
400
    type IntoIter = Iter<'a, T>;
401

            
402
1383
    fn into_iter(self) -> Iter<'a, T> {
403
1383
        self.iter()
404
1383
    }
405
}
406

            
407
#[stable(feature = "rust1", since = "1.0.0")]
408
#[cfg(not(feature = "ferrocene_certified"))]
409
impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
410
    type Item = &'a mut T;
411
    type IntoIter = IterMut<'a, T>;
412

            
413
    fn into_iter(self) -> IterMut<'a, T> {
414
        self.iter_mut()
415
    }
416
}
417

            
418
#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
419
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
420
#[cfg(not(feature = "ferrocene_certified"))]
421
impl<T, I, const N: usize> const Index<I> for [T; N]
422
where
423
    [T]: [const] Index<I>,
424
{
425
    type Output = <[T] as Index<I>>::Output;
426

            
427
    #[inline]
428
8
    fn index(&self, index: I) -> &Self::Output {
429
8
        Index::index(self as &[T], index)
430
8
    }
431
}
432

            
433
#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
434
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
435
#[cfg(not(feature = "ferrocene_certified"))]
436
impl<T, I, const N: usize> const IndexMut<I> for [T; N]
437
where
438
    [T]: [const] IndexMut<I>,
439
{
440
    #[inline]
441
1
    fn index_mut(&mut self, index: I) -> &mut Self::Output {
442
1
        IndexMut::index_mut(self as &mut [T], index)
443
1
    }
444
}
445

            
446
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
447
#[stable(feature = "rust1", since = "1.0.0")]
448
// blocked by PartialOrd
449
#[cfg(not(feature = "ferrocene_certified"))]
450
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
451
    #[inline]
452
    fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
453
        PartialOrd::partial_cmp(&&self[..], &&other[..])
454
    }
455
    #[inline]
456
    fn lt(&self, other: &[T; N]) -> bool {
457
        PartialOrd::lt(&&self[..], &&other[..])
458
    }
459
    #[inline]
460
    fn le(&self, other: &[T; N]) -> bool {
461
        PartialOrd::le(&&self[..], &&other[..])
462
    }
463
    #[inline]
464
    fn ge(&self, other: &[T; N]) -> bool {
465
        PartialOrd::ge(&&self[..], &&other[..])
466
    }
467
    #[inline]
468
    fn gt(&self, other: &[T; N]) -> bool {
469
        PartialOrd::gt(&&self[..], &&other[..])
470
    }
471
}
472

            
473
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
474
#[stable(feature = "rust1", since = "1.0.0")]
475
#[cfg(not(feature = "ferrocene_certified"))]
476
impl<T: Ord, const N: usize> Ord for [T; N] {
477
    #[inline]
478
    fn cmp(&self, other: &[T; N]) -> Ordering {
479
        Ord::cmp(&&self[..], &&other[..])
480
    }
481
}
482

            
483
#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
484
#[cfg(not(feature = "ferrocene_certified"))]
485
impl<T: Copy, const N: usize> Copy for [T; N] {}
486

            
487
#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
488
#[cfg(not(feature = "ferrocene_certified"))]
489
impl<T: Clone, const N: usize> Clone for [T; N] {
490
    #[inline]
491
    fn clone(&self) -> Self {
492
        SpecArrayClone::clone(self)
493
    }
494

            
495
    #[inline]
496
    fn clone_from(&mut self, other: &Self) {
497
        self.clone_from_slice(other);
498
    }
499
}
500

            
501
#[cfg(not(feature = "ferrocene_certified"))]
502
trait SpecArrayClone: Clone {
503
    fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
504
}
505

            
506
#[cfg(not(feature = "ferrocene_certified"))]
507
impl<T: Clone> SpecArrayClone for T {
508
    #[inline]
509
    default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
510
        from_trusted_iterator(array.iter().cloned())
511
    }
512
}
513

            
514
#[cfg(not(feature = "ferrocene_certified"))]
515
impl<T: Copy> SpecArrayClone for T {
516
    #[inline]
517
    fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
518
        *array
519
    }
520
}
521

            
522
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
523
// require Default to be implemented, and having different impl blocks for
524
// different numbers isn't supported yet.
525

            
526
#[cfg(not(feature = "ferrocene_certified"))]
527
macro_rules! array_impl_default {
528
    {$n:expr, $t:ident $($ts:ident)*} => {
529
        #[stable(since = "1.4.0", feature = "array_default")]
530
        impl<T> Default for [T; $n] where T: Default {
531
            fn default() -> [T; $n] {
532
                [$t::default(), $($ts::default()),*]
533
            }
534
        }
535
        array_impl_default!{($n - 1), $($ts)*}
536
    };
537
    {$n:expr,} => {
538
        #[stable(since = "1.4.0", feature = "array_default")]
539
        impl<T> Default for [T; $n] {
540
            fn default() -> [T; $n] { [] }
541
        }
542
    };
543
}
544

            
545
#[cfg(not(feature = "ferrocene_certified"))]
546
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}
547

            
548
impl<T, const N: usize> [T; N] {
549
    /// Returns an array of the same size as `self`, with function `f` applied to each element
550
    /// in order.
551
    ///
552
    /// If you don't necessarily need a new fixed-size array, consider using
553
    /// [`Iterator::map`] instead.
554
    ///
555
    ///
556
    /// # Note on performance and stack usage
557
    ///
558
    /// Unfortunately, usages of this method are currently not always optimized
559
    /// as well as they could be. This mainly concerns large arrays, as mapping
560
    /// over small arrays seem to be optimized just fine. Also note that in
561
    /// debug mode (i.e. without any optimizations), this method can use a lot
562
    /// of stack space (a few times the size of the array or more).
563
    ///
564
    /// Therefore, in performance-critical code, try to avoid using this method
565
    /// on large arrays or check the emitted code. Also try to avoid chained
566
    /// maps (e.g. `arr.map(...).map(...)`).
567
    ///
568
    /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
569
    /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
570
    /// really need a new array of the same size as the result. Rust's lazy
571
    /// iterators tend to get optimized very well.
572
    ///
573
    ///
574
    /// # Examples
575
    ///
576
    /// ```
577
    /// let x = [1, 2, 3];
578
    /// let y = x.map(|v| v + 1);
579
    /// assert_eq!(y, [2, 3, 4]);
580
    ///
581
    /// let x = [1, 2, 3];
582
    /// let mut temp = 0;
583
    /// let y = x.map(|v| { temp += 1; v * temp });
584
    /// assert_eq!(y, [1, 4, 9]);
585
    ///
586
    /// let x = ["Ferris", "Bueller's", "Day", "Off"];
587
    /// let y = x.map(|v| v.len());
588
    /// assert_eq!(y, [6, 9, 3, 3]);
589
    /// ```
590
    #[must_use]
591
    #[stable(feature = "array_map", since = "1.55.0")]
592
    #[cfg(not(feature = "ferrocene_certified"))]
593
    pub fn map<F, U>(self, f: F) -> [U; N]
594
    where
595
        F: FnMut(T) -> U,
596
    {
597
        self.try_map(NeverShortCircuit::wrap_mut_1(f)).0
598
    }
599

            
600
    /// A fallible function `f` applied to each element on array `self` in order to
601
    /// return an array the same size as `self` or the first error encountered.
602
    ///
603
    /// The return type of this function depends on the return type of the closure.
604
    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
605
    /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
606
    ///
607
    /// # Examples
608
    ///
609
    /// ```
610
    /// #![feature(array_try_map)]
611
    ///
612
    /// let a = ["1", "2", "3"];
613
    /// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
614
    /// assert_eq!(b, [2, 3, 4]);
615
    ///
616
    /// let a = ["1", "2a", "3"];
617
    /// let b = a.try_map(|v| v.parse::<u32>());
618
    /// assert!(b.is_err());
619
    ///
620
    /// use std::num::NonZero;
621
    ///
622
    /// let z = [1, 2, 0, 3, 4];
623
    /// assert_eq!(z.try_map(NonZero::new), None);
624
    ///
625
    /// let a = [1, 2, 3];
626
    /// let b = a.try_map(NonZero::new);
627
    /// let c = b.map(|x| x.map(NonZero::get));
628
    /// assert_eq!(c, Some(a));
629
    /// ```
630
    #[unstable(feature = "array_try_map", issue = "79711")]
631
    #[cfg(not(feature = "ferrocene_certified"))]
632
    pub fn try_map<R>(self, f: impl FnMut(T) -> R) -> ChangeOutputType<R, [R::Output; N]>
633
    where
634
        R: Try<Residual: Residual<[R::Output; N]>>,
635
    {
636
        drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f)))
637
    }
638

            
639
    /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
640
    #[stable(feature = "array_as_slice", since = "1.57.0")]
641
    #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")]
642
    pub const fn as_slice(&self) -> &[T] {
643
        self
644
    }
645

            
646
    /// Returns a mutable slice containing the entire array. Equivalent to
647
    /// `&mut s[..]`.
648
    #[stable(feature = "array_as_slice", since = "1.57.0")]
649
    #[rustc_const_stable(feature = "const_array_as_mut_slice", since = "1.89.0")]
650
    pub const fn as_mut_slice(&mut self) -> &mut [T] {
651
        self
652
    }
653

            
654
    /// Borrows each element and returns an array of references with the same
655
    /// size as `self`.
656
    ///
657
    ///
658
    /// # Example
659
    ///
660
    /// ```
661
    /// let floats = [3.1, 2.7, -1.0];
662
    /// let float_refs: [&f64; 3] = floats.each_ref();
663
    /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
664
    /// ```
665
    ///
666
    /// This method is particularly useful if combined with other methods, like
667
    /// [`map`](#method.map). This way, you can avoid moving the original
668
    /// array if its elements are not [`Copy`].
669
    ///
670
    /// ```
671
    /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
672
    /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
673
    /// assert_eq!(is_ascii, [true, false, true]);
674
    ///
675
    /// // We can still access the original array: it has not been moved.
676
    /// assert_eq!(strings.len(), 3);
677
    /// ```
678
    #[stable(feature = "array_methods", since = "1.77.0")]
679
    #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")]
680
    #[cfg(not(feature = "ferrocene_certified"))]
681
    pub const fn each_ref(&self) -> [&T; N] {
682
        let mut buf = [null::<T>(); N];
683

            
684
        // FIXME(const_trait_impl): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
685
        let mut i = 0;
686
        while i < N {
687
            buf[i] = &raw const self[i];
688

            
689
            i += 1;
690
        }
691

            
692
        // SAFETY: `*const T` has the same layout as `&T`, and we've also initialised each pointer as a valid reference.
693
        unsafe { transmute_unchecked(buf) }
694
    }
695

            
696
    /// Borrows each element mutably and returns an array of mutable references
697
    /// with the same size as `self`.
698
    ///
699
    ///
700
    /// # Example
701
    ///
702
    /// ```
703
    ///
704
    /// let mut floats = [3.1, 2.7, -1.0];
705
    /// let float_refs: [&mut f64; 3] = floats.each_mut();
706
    /// *float_refs[0] = 0.0;
707
    /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
708
    /// assert_eq!(floats, [0.0, 2.7, -1.0]);
709
    /// ```
710
    #[stable(feature = "array_methods", since = "1.77.0")]
711
    #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")]
712
    #[cfg(not(feature = "ferrocene_certified"))]
713
    pub const fn each_mut(&mut self) -> [&mut T; N] {
714
        let mut buf = [null_mut::<T>(); N];
715

            
716
        // FIXME(const_trait_impl): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
717
        let mut i = 0;
718
        while i < N {
719
            buf[i] = &raw mut self[i];
720

            
721
            i += 1;
722
        }
723

            
724
        // SAFETY: `*mut T` has the same layout as `&mut T`, and we've also initialised each pointer as a valid reference.
725
        unsafe { transmute_unchecked(buf) }
726
    }
727

            
728
    /// Divides one array reference into two at an index.
729
    ///
730
    /// The first will contain all indices from `[0, M)` (excluding
731
    /// the index `M` itself) and the second will contain all
732
    /// indices from `[M, N)` (excluding the index `N` itself).
733
    ///
734
    /// # Panics
735
    ///
736
    /// Panics if `M > N`.
737
    ///
738
    /// # Examples
739
    ///
740
    /// ```
741
    /// #![feature(split_array)]
742
    ///
743
    /// let v = [1, 2, 3, 4, 5, 6];
744
    ///
745
    /// {
746
    ///    let (left, right) = v.split_array_ref::<0>();
747
    ///    assert_eq!(left, &[]);
748
    ///    assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
749
    /// }
750
    ///
751
    /// {
752
    ///     let (left, right) = v.split_array_ref::<2>();
753
    ///     assert_eq!(left, &[1, 2]);
754
    ///     assert_eq!(right, &[3, 4, 5, 6]);
755
    /// }
756
    ///
757
    /// {
758
    ///     let (left, right) = v.split_array_ref::<6>();
759
    ///     assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
760
    ///     assert_eq!(right, &[]);
761
    /// }
762
    /// ```
763
    #[unstable(
764
        feature = "split_array",
765
        reason = "return type should have array as 2nd element",
766
        issue = "90091"
767
    )]
768
    #[inline]
769
    #[cfg(not(feature = "ferrocene_certified"))]
770
    pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
771
        self.split_first_chunk::<M>().unwrap()
772
    }
773

            
774
    /// Divides one mutable array reference into two at an index.
775
    ///
776
    /// The first will contain all indices from `[0, M)` (excluding
777
    /// the index `M` itself) and the second will contain all
778
    /// indices from `[M, N)` (excluding the index `N` itself).
779
    ///
780
    /// # Panics
781
    ///
782
    /// Panics if `M > N`.
783
    ///
784
    /// # Examples
785
    ///
786
    /// ```
787
    /// #![feature(split_array)]
788
    ///
789
    /// let mut v = [1, 0, 3, 0, 5, 6];
790
    /// let (left, right) = v.split_array_mut::<2>();
791
    /// assert_eq!(left, &mut [1, 0][..]);
792
    /// assert_eq!(right, &mut [3, 0, 5, 6]);
793
    /// left[1] = 2;
794
    /// right[1] = 4;
795
    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
796
    /// ```
797
    #[unstable(
798
        feature = "split_array",
799
        reason = "return type should have array as 2nd element",
800
        issue = "90091"
801
    )]
802
    #[inline]
803
    #[cfg(not(feature = "ferrocene_certified"))]
804
    pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
805
        self.split_first_chunk_mut::<M>().unwrap()
806
    }
807

            
808
    /// Divides one array reference into two at an index from the end.
809
    ///
810
    /// The first will contain all indices from `[0, N - M)` (excluding
811
    /// the index `N - M` itself) and the second will contain all
812
    /// indices from `[N - M, N)` (excluding the index `N` itself).
813
    ///
814
    /// # Panics
815
    ///
816
    /// Panics if `M > N`.
817
    ///
818
    /// # Examples
819
    ///
820
    /// ```
821
    /// #![feature(split_array)]
822
    ///
823
    /// let v = [1, 2, 3, 4, 5, 6];
824
    ///
825
    /// {
826
    ///    let (left, right) = v.rsplit_array_ref::<0>();
827
    ///    assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
828
    ///    assert_eq!(right, &[]);
829
    /// }
830
    ///
831
    /// {
832
    ///     let (left, right) = v.rsplit_array_ref::<2>();
833
    ///     assert_eq!(left, &[1, 2, 3, 4]);
834
    ///     assert_eq!(right, &[5, 6]);
835
    /// }
836
    ///
837
    /// {
838
    ///     let (left, right) = v.rsplit_array_ref::<6>();
839
    ///     assert_eq!(left, &[]);
840
    ///     assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
841
    /// }
842
    /// ```
843
    #[unstable(
844
        feature = "split_array",
845
        reason = "return type should have array as 2nd element",
846
        issue = "90091"
847
    )]
848
    #[inline]
849
    #[cfg(not(feature = "ferrocene_certified"))]
850
    pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
851
        self.split_last_chunk::<M>().unwrap()
852
    }
853

            
854
    /// Divides one mutable array reference into two at an index from the end.
855
    ///
856
    /// The first will contain all indices from `[0, N - M)` (excluding
857
    /// the index `N - M` itself) and the second will contain all
858
    /// indices from `[N - M, N)` (excluding the index `N` itself).
859
    ///
860
    /// # Panics
861
    ///
862
    /// Panics if `M > N`.
863
    ///
864
    /// # Examples
865
    ///
866
    /// ```
867
    /// #![feature(split_array)]
868
    ///
869
    /// let mut v = [1, 0, 3, 0, 5, 6];
870
    /// let (left, right) = v.rsplit_array_mut::<4>();
871
    /// assert_eq!(left, &mut [1, 0]);
872
    /// assert_eq!(right, &mut [3, 0, 5, 6][..]);
873
    /// left[1] = 2;
874
    /// right[1] = 4;
875
    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
876
    /// ```
877
    #[unstable(
878
        feature = "split_array",
879
        reason = "return type should have array as 2nd element",
880
        issue = "90091"
881
    )]
882
    #[inline]
883
    #[cfg(not(feature = "ferrocene_certified"))]
884
    pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
885
        self.split_last_chunk_mut::<M>().unwrap()
886
    }
887
}
888

            
889
/// Populate an array from the first `N` elements of `iter`
890
///
891
/// # Panics
892
///
893
/// If the iterator doesn't actually have enough items.
894
///
895
/// By depending on `TrustedLen`, however, we can do that check up-front (where
896
/// it easily optimizes away) so it doesn't impact the loop that fills the array.
897
#[inline]
898
#[cfg(not(feature = "ferrocene_certified"))]
899
fn from_trusted_iterator<T, const N: usize>(iter: impl UncheckedIterator<Item = T>) -> [T; N] {
900
    try_from_trusted_iterator(iter.map(NeverShortCircuit)).0
901
}
902

            
903
#[inline]
904
#[cfg(not(feature = "ferrocene_certified"))]
905
fn try_from_trusted_iterator<T, R, const N: usize>(
906
    iter: impl UncheckedIterator<Item = R>,
907
) -> ChangeOutputType<R, [T; N]>
908
where
909
    R: Try<Output = T>,
910
    R::Residual: Residual<[T; N]>,
911
{
912
    assert!(iter.size_hint().0 >= N);
913
    fn next<T>(mut iter: impl UncheckedIterator<Item = T>) -> impl FnMut(usize) -> T {
914
        move |_| {
915
            // SAFETY: We know that `from_fn` will call this at most N times,
916
            // and we checked to ensure that we have at least that many items.
917
            unsafe { iter.next_unchecked() }
918
        }
919
    }
920

            
921
    try_from_fn(next(iter))
922
}
923

            
924
/// Version of [`try_from_fn`] using a passed-in slice in order to avoid
925
/// needing to monomorphize for every array length.
926
///
927
/// This takes a generator rather than an iterator so that *at the type level*
928
/// it never needs to worry about running out of items.  When combined with
929
/// an infallible `Try` type, that means the loop canonicalizes easily, allowing
930
/// it to optimize well.
931
///
932
/// It would be *possible* to unify this and [`iter_next_chunk_erased`] into one
933
/// function that does the union of both things, but last time it was that way
934
/// it resulted in poor codegen from the "are there enough source items?" checks
935
/// not optimizing away.  So if you give it a shot, make sure to watch what
936
/// happens in the codegen tests.
937
#[inline]
938
#[cfg(not(feature = "ferrocene_certified"))]
939
fn try_from_fn_erased<T, R>(
940
    buffer: &mut [MaybeUninit<T>],
941
    mut generator: impl FnMut(usize) -> R,
942
) -> ControlFlow<R::Residual>
943
where
944
    R: Try<Output = T>,
945
{
946
    let mut guard = Guard { array_mut: buffer, initialized: 0 };
947

            
948
    while guard.initialized < guard.array_mut.len() {
949
        let item = generator(guard.initialized).branch()?;
950

            
951
        // SAFETY: The loop condition ensures we have space to push the item
952
        unsafe { guard.push_unchecked(item) };
953
    }
954

            
955
    mem::forget(guard);
956
    ControlFlow::Continue(())
957
}
958

            
959
/// Panic guard for incremental initialization of arrays.
960
///
961
/// Disarm the guard with `mem::forget` once the array has been initialized.
962
///
963
/// # Safety
964
///
965
/// All write accesses to this structure are unsafe and must maintain a correct
966
/// count of `initialized` elements.
967
///
968
/// To minimize indirection fields are still pub but callers should at least use
969
/// `push_unchecked` to signal that something unsafe is going on.
970
#[cfg(not(feature = "ferrocene_certified"))]
971
struct Guard<'a, T> {
972
    /// The array to be initialized.
973
    pub array_mut: &'a mut [MaybeUninit<T>],
974
    /// The number of items that have been initialized so far.
975
    pub initialized: usize,
976
}
977

            
978
#[cfg(not(feature = "ferrocene_certified"))]
979
impl<T> Guard<'_, T> {
980
    /// Adds an item to the array and updates the initialized item counter.
981
    ///
982
    /// # Safety
983
    ///
984
    /// No more than N elements must be initialized.
985
    #[inline]
986
17360
    pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
987
        // SAFETY: If `initialized` was correct before and the caller does not
988
        // invoke this method more than N times then writes will be in-bounds
989
        // and slots will not be initialized more than once.
990
17360
        unsafe {
991
17360
            self.array_mut.get_unchecked_mut(self.initialized).write(item);
992
17360
            self.initialized = self.initialized.unchecked_add(1);
993
17360
        }
994
17360
    }
995
}
996

            
997
#[cfg(not(feature = "ferrocene_certified"))]
998
impl<T> Drop for Guard<'_, T> {
999
    #[inline]
    fn drop(&mut self) {
        debug_assert!(self.initialized <= self.array_mut.len());
        // SAFETY: this slice will contain only initialized objects.
        unsafe {
            self.array_mut.get_unchecked_mut(..self.initialized).assume_init_drop();
        }
    }
}
/// Pulls `N` items from `iter` and returns them as an array. If the iterator
/// yields fewer than `N` items, `Err` is returned containing an iterator over
/// the already yielded items.
///
/// Since the iterator is passed as a mutable reference and this function calls
/// `next` at most `N` times, the iterator can still be used afterwards to
/// retrieve the remaining items.
///
/// If `iter.next()` panicks, all items already yielded by the iterator are
/// dropped.
///
/// Used for [`Iterator::next_chunk`].
#[inline]
#[cfg(not(feature = "ferrocene_certified"))]
pub(crate) fn iter_next_chunk<T, const N: usize>(
    iter: &mut impl Iterator<Item = T>,
) -> Result<[T; N], IntoIter<T, N>> {
    let mut array = [const { MaybeUninit::uninit() }; N];
    let r = iter_next_chunk_erased(&mut array, iter);
    match r {
        Ok(()) => {
            // SAFETY: All elements of `array` were populated.
            Ok(unsafe { MaybeUninit::array_assume_init(array) })
        }
        Err(initialized) => {
            // SAFETY: Only the first `initialized` elements were populated
            Err(unsafe { IntoIter::new_unchecked(array, 0..initialized) })
        }
    }
}
/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid
/// needing to monomorphize for every array length.
///
/// Unfortunately this loop has two exit conditions, the buffer filling up
/// or the iterator running out of items, making it tend to optimize poorly.
#[inline]
#[cfg(not(feature = "ferrocene_certified"))]
fn iter_next_chunk_erased<T>(
    buffer: &mut [MaybeUninit<T>],
    iter: &mut impl Iterator<Item = T>,
) -> Result<(), usize> {
    let mut guard = Guard { array_mut: buffer, initialized: 0 };
    while guard.initialized < guard.array_mut.len() {
        let Some(item) = iter.next() else {
            // Unlike `try_from_fn_erased`, we want to keep the partial results,
            // so we need to defuse the guard instead of using `?`.
            let initialized = guard.initialized;
            mem::forget(guard);
            return Err(initialized);
        };
        // SAFETY: The loop condition ensures we have space to push the item
        unsafe { guard.push_unchecked(item) };
    }
    mem::forget(guard);
    Ok(())
}