core/array/
mod.rs

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
7use crate::borrow::{Borrow, BorrowMut};
8use crate::cmp::Ordering;
9use crate::convert::Infallible;
10use crate::error::Error;
11use crate::fmt;
12use crate::hash::{self, Hash};
13use crate::intrinsics::transmute_unchecked;
14use crate::iter::{UncheckedIterator, repeat_n};
15use crate::mem::{self, MaybeUninit};
16use crate::ops::{
17    ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
18};
19use crate::ptr::{null, null_mut};
20use crate::slice::{Iter, IterMut};
21
22mod ascii;
23mod drain;
24mod equality;
25mod iter;
26
27pub(crate) use drain::drain_array_with;
28#[stable(feature = "array_value_iter", since = "1.51.0")]
29pub use iter::IntoIter;
30
31/// Creates an array of type `[T; N]` by repeatedly cloning a value.
32///
33/// This is the same as `[val; N]`, but it also works for types that do not
34/// implement [`Copy`].
35///
36/// The provided value will be used as an element of the resulting array and
37/// will be cloned N - 1 times to fill up the rest. If N is zero, the value
38/// will be dropped.
39///
40/// # Example
41///
42/// Creating multiple copies of a `String`:
43/// ```rust
44/// #![feature(array_repeat)]
45///
46/// use std::array;
47///
48/// let string = "Hello there!".to_string();
49/// let strings = array::repeat(string);
50/// assert_eq!(strings, ["Hello there!", "Hello there!"]);
51/// ```
52#[inline]
53#[unstable(feature = "array_repeat", issue = "126695")]
54pub fn repeat<T: Clone, const N: usize>(val: T) -> [T; N] {
55    from_trusted_iterator(repeat_n(val, N))
56}
57
58/// Creates an array where each element is produced by calling `f` with
59/// that element's index while walking forward through the array.
60///
61/// This is essentially the same as writing
62/// ```text
63/// [f(0), f(1), f(2), …, f(N - 2), f(N - 1)]
64/// ```
65/// and is similar to `(0..i).map(f)`, just for arrays not iterators.
66///
67/// If `N == 0`, this produces an empty array without ever calling `f`.
68///
69/// # Example
70///
71/// ```rust
72/// // type inference is helping us here, the way `from_fn` knows how many
73/// // elements to produce is the length of array down there: only arrays of
74/// // equal lengths can be compared, so the const generic parameter `N` is
75/// // inferred to be 5, thus creating array of 5 elements.
76///
77/// let array = core::array::from_fn(|i| i);
78/// // indexes are:    0  1  2  3  4
79/// assert_eq!(array, [0, 1, 2, 3, 4]);
80///
81/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2);
82/// // indexes are:     0  1  2  3  4  5   6   7
83/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]);
84///
85/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0);
86/// // indexes are:       0     1      2     3      4
87/// assert_eq!(bool_arr, [true, false, true, false, true]);
88/// ```
89///
90/// You can also capture things, for example to create an array full of clones
91/// where you can't just use `[item; N]` because it's not `Copy`:
92/// ```
93/// # // TBH `array::repeat` would be better for this, but it's not stable yet.
94/// let my_string = String::from("Hello");
95/// let clones: [String; 42] = std::array::from_fn(|_| my_string.clone());
96/// assert!(clones.iter().all(|x| *x == my_string));
97/// ```
98///
99/// The array is generated in ascending index order, starting from the front
100/// and going towards the back, so you can use closures with mutable state:
101/// ```
102/// let mut state = 1;
103/// let a = std::array::from_fn(|_| { let x = state; state *= 2; x });
104/// assert_eq!(a, [1, 2, 4, 8, 16, 32]);
105/// ```
106#[inline]
107#[stable(feature = "array_from_fn", since = "1.63.0")]
108pub fn from_fn<T, const N: usize, F>(f: F) -> [T; N]
109where
110    F: FnMut(usize) -> T,
111{
112    try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0
113}
114
115/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
116/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
117/// if any element creation was unsuccessful.
118///
119/// The return type of this function depends on the return type of the closure.
120/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
121/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
122///
123/// # Arguments
124///
125/// * `cb`: Callback where the passed argument is the current array index.
126///
127/// # Example
128///
129/// ```rust
130/// #![feature(array_try_from_fn)]
131///
132/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into());
133/// assert_eq!(array, Ok([0, 1, 2, 3, 4]));
134///
135/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into());
136/// assert!(array.is_err());
137///
138/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100));
139/// assert_eq!(array, Some([100, 101, 102, 103]));
140///
141/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100));
142/// assert_eq!(array, None);
143/// ```
144#[inline]
145#[unstable(feature = "array_try_from_fn", issue = "89379")]
146pub fn try_from_fn<R, const N: usize, F>(cb: F) -> ChangeOutputType<R, [R::Output; N]>
147where
148    F: FnMut(usize) -> R,
149    R: Try,
150    R::Residual: Residual<[R::Output; N]>,
151{
152    let mut array = [const { MaybeUninit::uninit() }; N];
153    match try_from_fn_erased(&mut array, cb) {
154        ControlFlow::Break(r) => FromResidual::from_residual(r),
155        ControlFlow::Continue(()) => {
156            // SAFETY: All elements of the array were populated.
157            try { unsafe { MaybeUninit::array_assume_init(array) } }
158        }
159    }
160}
161
162/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
163#[stable(feature = "array_from_ref", since = "1.53.0")]
164#[rustc_const_stable(feature = "const_array_from_ref_shared", since = "1.63.0")]
165pub const fn from_ref<T>(s: &T) -> &[T; 1] {
166    // SAFETY: Converting `&T` to `&[T; 1]` is sound.
167    unsafe { &*(s as *const T).cast::<[T; 1]>() }
168}
169
170/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying).
171#[stable(feature = "array_from_ref", since = "1.53.0")]
172#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")]
173pub const fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
174    // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound.
175    unsafe { &mut *(s as *mut T).cast::<[T; 1]>() }
176}
177
178/// The error type returned when a conversion from a slice to an array fails.
179#[stable(feature = "try_from", since = "1.34.0")]
180#[derive(Debug, Copy, Clone)]
181pub struct TryFromSliceError(());
182
183#[stable(feature = "core_array", since = "1.35.0")]
184impl fmt::Display for TryFromSliceError {
185    #[inline]
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        #[allow(deprecated)]
188        self.description().fmt(f)
189    }
190}
191
192#[stable(feature = "try_from", since = "1.34.0")]
193impl Error for TryFromSliceError {
194    #[allow(deprecated)]
195    fn description(&self) -> &str {
196        "could not convert slice to array"
197    }
198}
199
200#[stable(feature = "try_from_slice_error", since = "1.36.0")]
201#[rustc_const_unstable(feature = "const_try", issue = "74935")]
202impl const From<Infallible> for TryFromSliceError {
203    fn from(x: Infallible) -> TryFromSliceError {
204        match x {}
205    }
206}
207
208#[stable(feature = "rust1", since = "1.0.0")]
209impl<T, const N: usize> AsRef<[T]> for [T; N] {
210    #[inline]
211    fn as_ref(&self) -> &[T] {
212        &self[..]
213    }
214}
215
216#[stable(feature = "rust1", since = "1.0.0")]
217impl<T, const N: usize> AsMut<[T]> for [T; N] {
218    #[inline]
219    fn as_mut(&mut self) -> &mut [T] {
220        &mut self[..]
221    }
222}
223
224#[stable(feature = "array_borrow", since = "1.4.0")]
225impl<T, const N: usize> Borrow<[T]> for [T; N] {
226    fn borrow(&self) -> &[T] {
227        self
228    }
229}
230
231#[stable(feature = "array_borrow", since = "1.4.0")]
232impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
233    fn borrow_mut(&mut self) -> &mut [T] {
234        self
235    }
236}
237
238/// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
239/// Succeeds if `slice.len() == N`.
240///
241/// ```
242/// let bytes: [u8; 3] = [1, 0, 2];
243///
244/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
245/// assert_eq!(1, u16::from_le_bytes(bytes_head));
246///
247/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
248/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
249/// ```
250#[stable(feature = "try_from", since = "1.34.0")]
251impl<T, const N: usize> TryFrom<&[T]> for [T; N]
252where
253    T: Copy,
254{
255    type Error = TryFromSliceError;
256
257    #[inline]
258    fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
259        <&Self>::try_from(slice).copied()
260    }
261}
262
263/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
264/// Succeeds if `slice.len() == N`.
265///
266/// ```
267/// let mut bytes: [u8; 3] = [1, 0, 2];
268///
269/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
270/// assert_eq!(1, u16::from_le_bytes(bytes_head));
271///
272/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
273/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
274/// ```
275#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
276impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
277where
278    T: Copy,
279{
280    type Error = TryFromSliceError;
281
282    #[inline]
283    fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
284        <Self>::try_from(&*slice)
285    }
286}
287
288/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
289/// `slice.len() == N`.
290///
291/// ```
292/// let bytes: [u8; 3] = [1, 0, 2];
293///
294/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
295/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
296///
297/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
298/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
299/// ```
300#[stable(feature = "try_from", since = "1.34.0")]
301impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
302    type Error = TryFromSliceError;
303
304    #[inline]
305    fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> {
306        slice.as_array().ok_or(TryFromSliceError(()))
307    }
308}
309
310/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
311/// `&mut [T]`. Succeeds if `slice.len() == N`.
312///
313/// ```
314/// let mut bytes: [u8; 3] = [1, 0, 2];
315///
316/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
317/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
318///
319/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
320/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
321/// ```
322#[stable(feature = "try_from", since = "1.34.0")]
323impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
324    type Error = TryFromSliceError;
325
326    #[inline]
327    fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> {
328        slice.as_mut_array().ok_or(TryFromSliceError(()))
329    }
330}
331
332/// The hash of an array is the same as that of the corresponding slice,
333/// as required by the `Borrow` implementation.
334///
335/// ```
336/// use std::hash::BuildHasher;
337///
338/// let b = std::hash::RandomState::new();
339/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
340/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
341/// assert_eq!(b.hash_one(a), b.hash_one(s));
342/// ```
343#[stable(feature = "rust1", since = "1.0.0")]
344impl<T: Hash, const N: usize> Hash for [T; N] {
345    fn hash<H: hash::Hasher>(&self, state: &mut H) {
346        Hash::hash(&self[..], state)
347    }
348}
349
350#[stable(feature = "rust1", since = "1.0.0")]
351impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
352    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353        fmt::Debug::fmt(&&self[..], f)
354    }
355}
356
357#[stable(feature = "rust1", since = "1.0.0")]
358impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
359    type Item = &'a T;
360    type IntoIter = Iter<'a, T>;
361
362    fn into_iter(self) -> Iter<'a, T> {
363        self.iter()
364    }
365}
366
367#[stable(feature = "rust1", since = "1.0.0")]
368impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
369    type Item = &'a mut T;
370    type IntoIter = IterMut<'a, T>;
371
372    fn into_iter(self) -> IterMut<'a, T> {
373        self.iter_mut()
374    }
375}
376
377#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
378#[rustc_const_unstable(feature = "const_index", issue = "143775")]
379impl<T, I, const N: usize> const Index<I> for [T; N]
380where
381    [T]: ~const Index<I>,
382{
383    type Output = <[T] as Index<I>>::Output;
384
385    #[inline]
386    fn index(&self, index: I) -> &Self::Output {
387        Index::index(self as &[T], index)
388    }
389}
390
391#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
392#[rustc_const_unstable(feature = "const_index", issue = "143775")]
393impl<T, I, const N: usize> const IndexMut<I> for [T; N]
394where
395    [T]: ~const IndexMut<I>,
396{
397    #[inline]
398    fn index_mut(&mut self, index: I) -> &mut Self::Output {
399        IndexMut::index_mut(self as &mut [T], index)
400    }
401}
402
403/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
404#[stable(feature = "rust1", since = "1.0.0")]
405impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
406    #[inline]
407    fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
408        PartialOrd::partial_cmp(&&self[..], &&other[..])
409    }
410    #[inline]
411    fn lt(&self, other: &[T; N]) -> bool {
412        PartialOrd::lt(&&self[..], &&other[..])
413    }
414    #[inline]
415    fn le(&self, other: &[T; N]) -> bool {
416        PartialOrd::le(&&self[..], &&other[..])
417    }
418    #[inline]
419    fn ge(&self, other: &[T; N]) -> bool {
420        PartialOrd::ge(&&self[..], &&other[..])
421    }
422    #[inline]
423    fn gt(&self, other: &[T; N]) -> bool {
424        PartialOrd::gt(&&self[..], &&other[..])
425    }
426}
427
428/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
429#[stable(feature = "rust1", since = "1.0.0")]
430impl<T: Ord, const N: usize> Ord for [T; N] {
431    #[inline]
432    fn cmp(&self, other: &[T; N]) -> Ordering {
433        Ord::cmp(&&self[..], &&other[..])
434    }
435}
436
437#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
438impl<T: Copy, const N: usize> Copy for [T; N] {}
439
440#[stable(feature = "copy_clone_array_lib", since = "1.58.0")]
441impl<T: Clone, const N: usize> Clone for [T; N] {
442    #[inline]
443    fn clone(&self) -> Self {
444        SpecArrayClone::clone(self)
445    }
446
447    #[inline]
448    fn clone_from(&mut self, other: &Self) {
449        self.clone_from_slice(other);
450    }
451}
452
453trait SpecArrayClone: Clone {
454    fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
455}
456
457impl<T: Clone> SpecArrayClone for T {
458    #[inline]
459    default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
460        from_trusted_iterator(array.iter().cloned())
461    }
462}
463
464impl<T: Copy> SpecArrayClone for T {
465    #[inline]
466    fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
467        *array
468    }
469}
470
471// The Default impls cannot be done with const generics because `[T; 0]` doesn't
472// require Default to be implemented, and having different impl blocks for
473// different numbers isn't supported yet.
474
475macro_rules! array_impl_default {
476    {$n:expr, $t:ident $($ts:ident)*} => {
477        #[stable(since = "1.4.0", feature = "array_default")]
478        impl<T> Default for [T; $n] where T: Default {
479            fn default() -> [T; $n] {
480                [$t::default(), $($ts::default()),*]
481            }
482        }
483        array_impl_default!{($n - 1), $($ts)*}
484    };
485    {$n:expr,} => {
486        #[stable(since = "1.4.0", feature = "array_default")]
487        impl<T> Default for [T; $n] {
488            fn default() -> [T; $n] { [] }
489        }
490    };
491}
492
493array_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}
494
495impl<T, const N: usize> [T; N] {
496    /// Returns an array of the same size as `self`, with function `f` applied to each element
497    /// in order.
498    ///
499    /// If you don't necessarily need a new fixed-size array, consider using
500    /// [`Iterator::map`] instead.
501    ///
502    ///
503    /// # Note on performance and stack usage
504    ///
505    /// Unfortunately, usages of this method are currently not always optimized
506    /// as well as they could be. This mainly concerns large arrays, as mapping
507    /// over small arrays seem to be optimized just fine. Also note that in
508    /// debug mode (i.e. without any optimizations), this method can use a lot
509    /// of stack space (a few times the size of the array or more).
510    ///
511    /// Therefore, in performance-critical code, try to avoid using this method
512    /// on large arrays or check the emitted code. Also try to avoid chained
513    /// maps (e.g. `arr.map(...).map(...)`).
514    ///
515    /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
516    /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
517    /// really need a new array of the same size as the result. Rust's lazy
518    /// iterators tend to get optimized very well.
519    ///
520    ///
521    /// # Examples
522    ///
523    /// ```
524    /// let x = [1, 2, 3];
525    /// let y = x.map(|v| v + 1);
526    /// assert_eq!(y, [2, 3, 4]);
527    ///
528    /// let x = [1, 2, 3];
529    /// let mut temp = 0;
530    /// let y = x.map(|v| { temp += 1; v * temp });
531    /// assert_eq!(y, [1, 4, 9]);
532    ///
533    /// let x = ["Ferris", "Bueller's", "Day", "Off"];
534    /// let y = x.map(|v| v.len());
535    /// assert_eq!(y, [6, 9, 3, 3]);
536    /// ```
537    #[must_use]
538    #[stable(feature = "array_map", since = "1.55.0")]
539    pub fn map<F, U>(self, f: F) -> [U; N]
540    where
541        F: FnMut(T) -> U,
542    {
543        self.try_map(NeverShortCircuit::wrap_mut_1(f)).0
544    }
545
546    /// A fallible function `f` applied to each element on array `self` in order to
547    /// return an array the same size as `self` or the first error encountered.
548    ///
549    /// The return type of this function depends on the return type of the closure.
550    /// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
551    /// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
552    ///
553    /// # Examples
554    ///
555    /// ```
556    /// #![feature(array_try_map)]
557    ///
558    /// let a = ["1", "2", "3"];
559    /// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
560    /// assert_eq!(b, [2, 3, 4]);
561    ///
562    /// let a = ["1", "2a", "3"];
563    /// let b = a.try_map(|v| v.parse::<u32>());
564    /// assert!(b.is_err());
565    ///
566    /// use std::num::NonZero;
567    ///
568    /// let z = [1, 2, 0, 3, 4];
569    /// assert_eq!(z.try_map(NonZero::new), None);
570    ///
571    /// let a = [1, 2, 3];
572    /// let b = a.try_map(NonZero::new);
573    /// let c = b.map(|x| x.map(NonZero::get));
574    /// assert_eq!(c, Some(a));
575    /// ```
576    #[unstable(feature = "array_try_map", issue = "79711")]
577    pub fn try_map<R>(self, f: impl FnMut(T) -> R) -> ChangeOutputType<R, [R::Output; N]>
578    where
579        R: Try<Residual: Residual<[R::Output; N]>>,
580    {
581        drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f)))
582    }
583
584    /// Returns a slice containing the entire array. Equivalent to `&s[..]`.
585    #[stable(feature = "array_as_slice", since = "1.57.0")]
586    #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")]
587    pub const fn as_slice(&self) -> &[T] {
588        self
589    }
590
591    /// Returns a mutable slice containing the entire array. Equivalent to
592    /// `&mut s[..]`.
593    #[stable(feature = "array_as_slice", since = "1.57.0")]
594    #[rustc_const_stable(feature = "const_array_as_mut_slice", since = "1.89.0")]
595    pub const fn as_mut_slice(&mut self) -> &mut [T] {
596        self
597    }
598
599    /// Borrows each element and returns an array of references with the same
600    /// size as `self`.
601    ///
602    ///
603    /// # Example
604    ///
605    /// ```
606    /// let floats = [3.1, 2.7, -1.0];
607    /// let float_refs: [&f64; 3] = floats.each_ref();
608    /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
609    /// ```
610    ///
611    /// This method is particularly useful if combined with other methods, like
612    /// [`map`](#method.map). This way, you can avoid moving the original
613    /// array if its elements are not [`Copy`].
614    ///
615    /// ```
616    /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
617    /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
618    /// assert_eq!(is_ascii, [true, false, true]);
619    ///
620    /// // We can still access the original array: it has not been moved.
621    /// assert_eq!(strings.len(), 3);
622    /// ```
623    #[stable(feature = "array_methods", since = "1.77.0")]
624    #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
625    pub const fn each_ref(&self) -> [&T; N] {
626        let mut buf = [null::<T>(); N];
627
628        // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
629        let mut i = 0;
630        while i < N {
631            buf[i] = &raw const self[i];
632
633            i += 1;
634        }
635
636        // SAFETY: `*const T` has the same layout as `&T`, and we've also initialised each pointer as a valid reference.
637        unsafe { transmute_unchecked(buf) }
638    }
639
640    /// Borrows each element mutably and returns an array of mutable references
641    /// with the same size as `self`.
642    ///
643    ///
644    /// # Example
645    ///
646    /// ```
647    ///
648    /// let mut floats = [3.1, 2.7, -1.0];
649    /// let float_refs: [&mut f64; 3] = floats.each_mut();
650    /// *float_refs[0] = 0.0;
651    /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
652    /// assert_eq!(floats, [0.0, 2.7, -1.0]);
653    /// ```
654    #[stable(feature = "array_methods", since = "1.77.0")]
655    #[rustc_const_unstable(feature = "const_array_each_ref", issue = "133289")]
656    pub const fn each_mut(&mut self) -> [&mut T; N] {
657        let mut buf = [null_mut::<T>(); N];
658
659        // FIXME(const-hack): We would like to simply use iterators for this (as in the original implementation), but this is not allowed in constant expressions.
660        let mut i = 0;
661        while i < N {
662            buf[i] = &raw mut self[i];
663
664            i += 1;
665        }
666
667        // SAFETY: `*mut T` has the same layout as `&mut T`, and we've also initialised each pointer as a valid reference.
668        unsafe { transmute_unchecked(buf) }
669    }
670
671    /// Divides one array reference into two at an index.
672    ///
673    /// The first will contain all indices from `[0, M)` (excluding
674    /// the index `M` itself) and the second will contain all
675    /// indices from `[M, N)` (excluding the index `N` itself).
676    ///
677    /// # Panics
678    ///
679    /// Panics if `M > N`.
680    ///
681    /// # Examples
682    ///
683    /// ```
684    /// #![feature(split_array)]
685    ///
686    /// let v = [1, 2, 3, 4, 5, 6];
687    ///
688    /// {
689    ///    let (left, right) = v.split_array_ref::<0>();
690    ///    assert_eq!(left, &[]);
691    ///    assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
692    /// }
693    ///
694    /// {
695    ///     let (left, right) = v.split_array_ref::<2>();
696    ///     assert_eq!(left, &[1, 2]);
697    ///     assert_eq!(right, &[3, 4, 5, 6]);
698    /// }
699    ///
700    /// {
701    ///     let (left, right) = v.split_array_ref::<6>();
702    ///     assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
703    ///     assert_eq!(right, &[]);
704    /// }
705    /// ```
706    #[unstable(
707        feature = "split_array",
708        reason = "return type should have array as 2nd element",
709        issue = "90091"
710    )]
711    #[inline]
712    pub fn split_array_ref<const M: usize>(&self) -> (&[T; M], &[T]) {
713        self.split_first_chunk::<M>().unwrap()
714    }
715
716    /// Divides one mutable array reference into two at an index.
717    ///
718    /// The first will contain all indices from `[0, M)` (excluding
719    /// the index `M` itself) and the second will contain all
720    /// indices from `[M, N)` (excluding the index `N` itself).
721    ///
722    /// # Panics
723    ///
724    /// Panics if `M > N`.
725    ///
726    /// # Examples
727    ///
728    /// ```
729    /// #![feature(split_array)]
730    ///
731    /// let mut v = [1, 0, 3, 0, 5, 6];
732    /// let (left, right) = v.split_array_mut::<2>();
733    /// assert_eq!(left, &mut [1, 0][..]);
734    /// assert_eq!(right, &mut [3, 0, 5, 6]);
735    /// left[1] = 2;
736    /// right[1] = 4;
737    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
738    /// ```
739    #[unstable(
740        feature = "split_array",
741        reason = "return type should have array as 2nd element",
742        issue = "90091"
743    )]
744    #[inline]
745    pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
746        self.split_first_chunk_mut::<M>().unwrap()
747    }
748
749    /// Divides one array reference into two at an index from the end.
750    ///
751    /// The first will contain all indices from `[0, N - M)` (excluding
752    /// the index `N - M` itself) and the second will contain all
753    /// indices from `[N - M, N)` (excluding the index `N` itself).
754    ///
755    /// # Panics
756    ///
757    /// Panics if `M > N`.
758    ///
759    /// # Examples
760    ///
761    /// ```
762    /// #![feature(split_array)]
763    ///
764    /// let v = [1, 2, 3, 4, 5, 6];
765    ///
766    /// {
767    ///    let (left, right) = v.rsplit_array_ref::<0>();
768    ///    assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
769    ///    assert_eq!(right, &[]);
770    /// }
771    ///
772    /// {
773    ///     let (left, right) = v.rsplit_array_ref::<2>();
774    ///     assert_eq!(left, &[1, 2, 3, 4]);
775    ///     assert_eq!(right, &[5, 6]);
776    /// }
777    ///
778    /// {
779    ///     let (left, right) = v.rsplit_array_ref::<6>();
780    ///     assert_eq!(left, &[]);
781    ///     assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
782    /// }
783    /// ```
784    #[unstable(
785        feature = "split_array",
786        reason = "return type should have array as 2nd element",
787        issue = "90091"
788    )]
789    #[inline]
790    pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
791        self.split_last_chunk::<M>().unwrap()
792    }
793
794    /// Divides one mutable array reference into two at an index from the end.
795    ///
796    /// The first will contain all indices from `[0, N - M)` (excluding
797    /// the index `N - M` itself) and the second will contain all
798    /// indices from `[N - M, N)` (excluding the index `N` itself).
799    ///
800    /// # Panics
801    ///
802    /// Panics if `M > N`.
803    ///
804    /// # Examples
805    ///
806    /// ```
807    /// #![feature(split_array)]
808    ///
809    /// let mut v = [1, 0, 3, 0, 5, 6];
810    /// let (left, right) = v.rsplit_array_mut::<4>();
811    /// assert_eq!(left, &mut [1, 0]);
812    /// assert_eq!(right, &mut [3, 0, 5, 6][..]);
813    /// left[1] = 2;
814    /// right[1] = 4;
815    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
816    /// ```
817    #[unstable(
818        feature = "split_array",
819        reason = "return type should have array as 2nd element",
820        issue = "90091"
821    )]
822    #[inline]
823    pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
824        self.split_last_chunk_mut::<M>().unwrap()
825    }
826}
827
828/// Populate an array from the first `N` elements of `iter`
829///
830/// # Panics
831///
832/// If the iterator doesn't actually have enough items.
833///
834/// By depending on `TrustedLen`, however, we can do that check up-front (where
835/// it easily optimizes away) so it doesn't impact the loop that fills the array.
836#[inline]
837fn from_trusted_iterator<T, const N: usize>(iter: impl UncheckedIterator<Item = T>) -> [T; N] {
838    try_from_trusted_iterator(iter.map(NeverShortCircuit)).0
839}
840
841#[inline]
842fn try_from_trusted_iterator<T, R, const N: usize>(
843    iter: impl UncheckedIterator<Item = R>,
844) -> ChangeOutputType<R, [T; N]>
845where
846    R: Try<Output = T>,
847    R::Residual: Residual<[T; N]>,
848{
849    assert!(iter.size_hint().0 >= N);
850    fn next<T>(mut iter: impl UncheckedIterator<Item = T>) -> impl FnMut(usize) -> T {
851        move |_| {
852            // SAFETY: We know that `from_fn` will call this at most N times,
853            // and we checked to ensure that we have at least that many items.
854            unsafe { iter.next_unchecked() }
855        }
856    }
857
858    try_from_fn(next(iter))
859}
860
861/// Version of [`try_from_fn`] using a passed-in slice in order to avoid
862/// needing to monomorphize for every array length.
863///
864/// This takes a generator rather than an iterator so that *at the type level*
865/// it never needs to worry about running out of items.  When combined with
866/// an infallible `Try` type, that means the loop canonicalizes easily, allowing
867/// it to optimize well.
868///
869/// It would be *possible* to unify this and [`iter_next_chunk_erased`] into one
870/// function that does the union of both things, but last time it was that way
871/// it resulted in poor codegen from the "are there enough source items?" checks
872/// not optimizing away.  So if you give it a shot, make sure to watch what
873/// happens in the codegen tests.
874#[inline]
875fn try_from_fn_erased<T, R>(
876    buffer: &mut [MaybeUninit<T>],
877    mut generator: impl FnMut(usize) -> R,
878) -> ControlFlow<R::Residual>
879where
880    R: Try<Output = T>,
881{
882    let mut guard = Guard { array_mut: buffer, initialized: 0 };
883
884    while guard.initialized < guard.array_mut.len() {
885        let item = generator(guard.initialized).branch()?;
886
887        // SAFETY: The loop condition ensures we have space to push the item
888        unsafe { guard.push_unchecked(item) };
889    }
890
891    mem::forget(guard);
892    ControlFlow::Continue(())
893}
894
895/// Panic guard for incremental initialization of arrays.
896///
897/// Disarm the guard with `mem::forget` once the array has been initialized.
898///
899/// # Safety
900///
901/// All write accesses to this structure are unsafe and must maintain a correct
902/// count of `initialized` elements.
903///
904/// To minimize indirection fields are still pub but callers should at least use
905/// `push_unchecked` to signal that something unsafe is going on.
906struct Guard<'a, T> {
907    /// The array to be initialized.
908    pub array_mut: &'a mut [MaybeUninit<T>],
909    /// The number of items that have been initialized so far.
910    pub initialized: usize,
911}
912
913impl<T> Guard<'_, T> {
914    /// Adds an item to the array and updates the initialized item counter.
915    ///
916    /// # Safety
917    ///
918    /// No more than N elements must be initialized.
919    #[inline]
920    pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
921        // SAFETY: If `initialized` was correct before and the caller does not
922        // invoke this method more than N times then writes will be in-bounds
923        // and slots will not be initialized more than once.
924        unsafe {
925            self.array_mut.get_unchecked_mut(self.initialized).write(item);
926            self.initialized = self.initialized.unchecked_add(1);
927        }
928    }
929}
930
931impl<T> Drop for Guard<'_, T> {
932    #[inline]
933    fn drop(&mut self) {
934        debug_assert!(self.initialized <= self.array_mut.len());
935
936        // SAFETY: this slice will contain only initialized objects.
937        unsafe {
938            self.array_mut.get_unchecked_mut(..self.initialized).assume_init_drop();
939        }
940    }
941}
942
943/// Pulls `N` items from `iter` and returns them as an array. If the iterator
944/// yields fewer than `N` items, `Err` is returned containing an iterator over
945/// the already yielded items.
946///
947/// Since the iterator is passed as a mutable reference and this function calls
948/// `next` at most `N` times, the iterator can still be used afterwards to
949/// retrieve the remaining items.
950///
951/// If `iter.next()` panicks, all items already yielded by the iterator are
952/// dropped.
953///
954/// Used for [`Iterator::next_chunk`].
955#[inline]
956pub(crate) fn iter_next_chunk<T, const N: usize>(
957    iter: &mut impl Iterator<Item = T>,
958) -> Result<[T; N], IntoIter<T, N>> {
959    let mut array = [const { MaybeUninit::uninit() }; N];
960    let r = iter_next_chunk_erased(&mut array, iter);
961    match r {
962        Ok(()) => {
963            // SAFETY: All elements of `array` were populated.
964            Ok(unsafe { MaybeUninit::array_assume_init(array) })
965        }
966        Err(initialized) => {
967            // SAFETY: Only the first `initialized` elements were populated
968            Err(unsafe { IntoIter::new_unchecked(array, 0..initialized) })
969        }
970    }
971}
972
973/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid
974/// needing to monomorphize for every array length.
975///
976/// Unfortunately this loop has two exit conditions, the buffer filling up
977/// or the iterator running out of items, making it tend to optimize poorly.
978#[inline]
979fn iter_next_chunk_erased<T>(
980    buffer: &mut [MaybeUninit<T>],
981    iter: &mut impl Iterator<Item = T>,
982) -> Result<(), usize> {
983    let mut guard = Guard { array_mut: buffer, initialized: 0 };
984    while guard.initialized < guard.array_mut.len() {
985        let Some(item) = iter.next() else {
986            // Unlike `try_from_fn_erased`, we want to keep the partial results,
987            // so we need to defuse the guard instead of using `?`.
988            let initialized = guard.initialized;
989            mem::forget(guard);
990            return Err(initialized);
991        };
992
993        // SAFETY: The loop condition ensures we have space to push the item
994        unsafe { guard.push_unchecked(item) };
995    }
996
997    mem::forget(guard);
998    Ok(())
999}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy