2022-04-30 12:01:31 -05:00
//! Utilities for the array primitive type.
2015-07-20 11:21:02 -07:00
//!
2020-12-19 08:23:59 -05:00
//! *[See also the array primitive type](array).*
2014-10-31 05:41:25 -04:00
2024-11-01 22:08:23 +01:00
#![ stable(feature = " core_array " , since = " 1.35.0 " ) ]
2015-03-23 14:01:28 -07:00
2019-04-15 11:23:21 +09:00
use crate ::borrow ::{ Borrow , BorrowMut } ;
use crate ::cmp ::Ordering ;
2024-03-25 11:02:02 -07:00
use crate ::convert ::Infallible ;
2022-07-29 18:54:47 +00:00
use crate ::error ::Error ;
2019-04-15 11:23:21 +09:00
use crate ::fmt ;
use crate ::hash ::{ self , Hash } ;
2024-11-21 12:16:00 +01:00
use crate ::intrinsics ::transmute_unchecked ;
2023-12-20 00:14:25 +01:00
use crate ::iter ::{ UncheckedIterator , repeat_n } ;
2021-02-14 14:42:47 +01:00
use crate ::mem ::{ self , MaybeUninit } ;
2021-11-26 23:09:34 -08:00
use crate ::ops ::{
ChangeOutputType , ControlFlow , FromResidual , Index , IndexMut , NeverShortCircuit , Residual , Try ,
} ;
2024-11-21 12:16:00 +01:00
use crate ::ptr ::{ null , null_mut } ;
2019-04-15 11:23:21 +09:00
use crate ::slice ::{ Iter , IterMut } ;
2014-10-31 05:41:25 -04:00
2023-04-29 14:45:36 -07:00
mod ascii ;
2023-02-02 20:58:22 -08:00
mod drain ;
2021-05-30 10:23:50 -07:00
mod equality ;
2019-07-25 00:39:39 +02:00
mod iter ;
2023-02-02 20:58:22 -08:00
pub ( crate ) use drain ::drain_array_with ;
2020-12-29 09:16:46 +01:00
#[ stable(feature = " array_value_iter " , since = " 1.51.0 " ) ]
2019-07-25 00:39:39 +02:00
pub use iter ::IntoIter ;
2023-12-19 19:30:52 +01:00
/// Creates an array of type `[T; N]` by repeatedly cloning a value.
///
2023-12-20 00:14:25 +01:00
/// This is the same as `[val; N]`, but it also works for types that do not
/// implement [`Copy`].
///
/// The provided value will be used as an element of the resulting array and
/// will be cloned N - 1 times to fill up the rest. If N is zero, the value
/// will be dropped.
2023-12-19 19:30:52 +01:00
///
/// # Example
///
2024-08-31 14:57:38 +09:00
/// Creating multiple copies of a `String`:
2023-12-19 19:30:52 +01:00
/// ```rust
/// #![feature(array_repeat)]
///
/// use std::array;
///
/// let string = "Hello there!".to_string();
/// let strings = array::repeat(string);
/// assert_eq!(strings, ["Hello there!", "Hello there!"]);
/// ```
#[ inline ]
2024-06-19 17:48:00 +02:00
#[ unstable(feature = " array_repeat " , issue = " 126695 " ) ]
2023-12-19 19:30:52 +01:00
pub fn repeat < T : Clone , const N : usize > ( val : T ) -> [ T ; N ] {
2023-12-20 00:14:25 +01:00
from_trusted_iterator ( repeat_n ( val , N ) )
2023-12-19 19:30:52 +01:00
}
2022-11-24 19:24:37 +01:00
/// Creates an array of type [T; N], where each element `T` is the returned value from `cb`
/// using that element's index.
2021-09-30 07:49:32 -03:00
///
/// # Arguments
///
/// * `cb`: Callback where the passed argument is the current array index.
///
/// # Example
///
/// ```rust
2022-08-12 22:43:52 +03:00
/// // type inference is helping us here, the way `from_fn` knows how many
/// // elements to produce is the length of array down there: only arrays of
/// // equal lengths can be compared, so the const generic parameter `N` is
/// // inferred to be 5, thus creating array of 5 elements.
2022-11-24 19:24:37 +01:00
///
2022-11-25 10:05:07 +01:00
/// let array = core::array::from_fn(|i| i);
2022-11-24 19:24:37 +01:00
/// // indexes are: 0 1 2 3 4
2021-09-30 07:49:32 -03:00
/// assert_eq!(array, [0, 1, 2, 3, 4]);
2022-11-24 19:24:37 +01:00
///
2022-11-25 10:05:07 +01:00
/// let array2: [usize; 8] = core::array::from_fn(|i| i * 2);
2022-11-24 19:24:37 +01:00
/// // indexes are: 0 1 2 3 4 5 6 7
/// assert_eq!(array2, [0, 2, 4, 6, 8, 10, 12, 14]);
///
2022-11-25 10:05:07 +01:00
/// let bool_arr = core::array::from_fn::<_, 5, _>(|i| i % 2 == 0);
2022-11-24 19:24:37 +01:00
/// // indexes are: 0 1 2 3 4
/// assert_eq!(bool_arr, [true, false, true, false, true]);
2021-09-30 07:49:32 -03:00
/// ```
#[ inline ]
2022-05-20 11:04:13 -03:00
#[ stable(feature = " array_from_fn " , since = " 1.63.0 " ) ]
2023-02-03 03:27:51 -08:00
pub fn from_fn < T , const N : usize , F > ( cb : F ) -> [ T ; N ]
2021-09-30 07:49:32 -03:00
where
F : FnMut ( usize ) -> T ,
{
2023-02-03 03:27:51 -08:00
try_from_fn ( NeverShortCircuit ::wrap_mut_1 ( cb ) ) . 0
2021-09-30 07:49:32 -03:00
}
/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
2021-11-26 23:09:34 -08:00
/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error
2021-09-30 07:49:32 -03:00
/// if any element creation was unsuccessful.
///
2021-11-26 23:09:34 -08:00
/// The return type of this function depends on the return type of the closure.
2022-12-15 14:05:01 +01:00
/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
2021-11-26 23:09:34 -08:00
/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
///
2021-09-30 07:49:32 -03:00
/// # Arguments
///
/// * `cb`: Callback where the passed argument is the current array index.
///
/// # Example
///
/// ```rust
2022-05-20 11:04:13 -03:00
/// #![feature(array_try_from_fn)]
2021-09-30 07:49:32 -03:00
///
2021-11-26 23:09:34 -08:00
/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into());
2021-09-30 07:49:32 -03:00
/// assert_eq!(array, Ok([0, 1, 2, 3, 4]));
///
2021-11-26 23:09:34 -08:00
/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into());
/// assert!(array.is_err());
///
/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100));
/// assert_eq!(array, Some([100, 101, 102, 103]));
///
/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100));
/// assert_eq!(array, None);
2021-09-30 07:49:32 -03:00
/// ```
#[ inline ]
2022-05-20 11:04:13 -03:00
#[ unstable(feature = " array_try_from_fn " , issue = " 89379 " ) ]
pub fn try_from_fn < R , const N : usize , F > ( cb : F ) -> ChangeOutputType < R , [ R ::Output ; N ] >
2021-09-30 07:49:32 -03:00
where
2021-11-26 23:09:34 -08:00
F : FnMut ( usize ) -> R ,
R : Try ,
R ::Residual : Residual < [ R ::Output ; N ] > ,
2021-09-30 07:49:32 -03:00
{
2024-05-12 21:37:53 -07:00
let mut array = [ const { MaybeUninit ::uninit ( ) } ; N ] ;
2023-02-03 03:27:51 -08:00
match try_from_fn_erased ( & mut array , cb ) {
ControlFlow ::Break ( r ) = > FromResidual ::from_residual ( r ) ,
ControlFlow ::Continue ( ( ) ) = > {
// SAFETY: All elements of the array were populated.
try { unsafe { MaybeUninit ::array_assume_init ( array ) } }
}
}
2021-09-30 07:49:32 -03:00
}
2020-09-22 21:35:43 +02:00
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
2021-04-11 22:06:32 +03:00
#[ stable(feature = " array_from_ref " , since = " 1.53.0 " ) ]
2022-05-24 22:33:31 +04:00
#[ rustc_const_stable(feature = " const_array_from_ref_shared " , since = " 1.63.0 " ) ]
2021-10-22 11:15:56 +03:00
pub const fn from_ref < T > ( s : & T ) -> & [ T ; 1 ] {
2020-09-22 21:35:43 +02:00
// SAFETY: Converting `&T` to `&[T; 1]` is sound.
unsafe { & * ( s as * const T ) . cast ::< [ T ; 1 ] > ( ) }
}
/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying).
2021-04-11 22:06:32 +03:00
#[ stable(feature = " array_from_ref " , since = " 1.53.0 " ) ]
2024-10-14 10:22:50 -07:00
#[ rustc_const_stable(feature = " const_array_from_ref " , since = " 1.83.0 " ) ]
2021-10-22 11:15:56 +03:00
pub const fn from_mut < T > ( s : & mut T ) -> & mut [ T ; 1 ] {
2020-09-22 21:35:43 +02:00
// SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound.
unsafe { & mut * ( s as * mut T ) . cast ::< [ T ; 1 ] > ( ) }
}
2017-09-21 16:35:23 -04:00
/// The error type returned when a conversion from a slice to an array fails.
2019-02-08 15:00:47 +01:00
#[ stable(feature = " try_from " , since = " 1.34.0 " ) ]
2024-11-01 22:08:23 +01:00
#[ rustc_allowed_through_unstable_modules ]
2017-09-21 16:35:23 -04:00
#[ derive(Debug, Copy, Clone) ]
pub struct TryFromSliceError ( ( ) ) ;
2024-11-01 22:08:23 +01:00
#[ stable(feature = " core_array " , since = " 1.35.0 " ) ]
2017-09-29 11:15:05 -04:00
impl fmt ::Display for TryFromSliceError {
#[ inline ]
2019-04-19 01:37:12 +02:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2023-01-10 15:59:47 +01:00
#[ allow(deprecated) ]
self . description ( ) . fmt ( f )
2017-09-29 11:15:05 -04:00
}
}
2022-07-29 18:54:47 +00:00
#[ stable(feature = " try_from " , since = " 1.34.0 " ) ]
impl Error for TryFromSliceError {
#[ allow(deprecated) ]
fn description ( & self ) -> & str {
2017-09-29 11:15:05 -04:00
" could not convert slice to array "
}
}
2019-04-26 12:45:26 -07:00
#[ stable(feature = " try_from_slice_error " , since = " 1.36.0 " ) ]
2023-04-16 06:49:27 +00:00
impl From < Infallible > for TryFromSliceError {
2019-04-26 12:45:26 -07:00
fn from ( x : Infallible ) -> TryFromSliceError {
match x { }
}
}
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-04 13:30:09 +03:00
impl < T , const N : usize > AsRef < [ T ] > for [ T ; N ] {
2019-07-25 18:06:26 +02:00
#[ inline ]
fn as_ref ( & self ) -> & [ T ] {
& self [ .. ]
2015-12-02 17:31:49 -08:00
}
}
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-04 13:30:09 +03:00
impl < T , const N : usize > AsMut < [ T ] > for [ T ; N ] {
2019-07-25 18:06:26 +02:00
#[ inline ]
fn as_mut ( & mut self ) -> & mut [ T ] {
& mut self [ .. ]
2015-12-02 17:31:49 -08:00
}
}
2019-07-25 18:06:26 +02:00
#[ stable(feature = " array_borrow " , since = " 1.4.0 " ) ]
2023-04-16 06:49:27 +00:00
impl < T , const N : usize > Borrow < [ T ] > for [ T ; N ] {
2019-07-25 18:06:26 +02:00
fn borrow ( & self ) -> & [ T ] {
self
2014-10-31 05:41:25 -04:00
}
}
2019-07-25 18:06:26 +02:00
#[ stable(feature = " array_borrow " , since = " 1.4.0 " ) ]
2023-04-16 06:49:27 +00:00
impl < T , const N : usize > BorrowMut < [ T ] > for [ T ; N ] {
2019-07-25 18:06:26 +02:00
fn borrow_mut ( & mut self ) -> & mut [ T ] {
self
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2024-11-26 21:49:28 +01:00
/// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
/// Succeeds if `slice.len() == N`.
2022-09-10 19:37:07 -07:00
///
/// ```
/// let bytes: [u8; 3] = [1, 0, 2];
///
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
///
/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
/// ```
2019-07-25 18:06:26 +02:00
#[ stable(feature = " try_from " , since = " 1.34.0 " ) ]
impl < T , const N : usize > TryFrom < & [ T ] > for [ T ; N ]
where
T : Copy ,
{
type Error = TryFromSliceError ;
2023-05-25 18:24:27 -04:00
#[ inline ]
2019-07-25 18:06:26 +02:00
fn try_from ( slice : & [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
2023-11-03 17:11:39 +01:00
< & Self > ::try_from ( slice ) . copied ( )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2022-09-10 19:37:07 -07:00
/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
/// Succeeds if `slice.len() == N`.
///
/// ```
/// let mut bytes: [u8; 3] = [1, 0, 2];
///
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
///
/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
/// ```
2021-12-04 17:17:12 +01:00
#[ stable(feature = " try_from_mut_slice_to_array " , since = " 1.59.0 " ) ]
2021-11-20 21:40:41 +09:00
impl < T , const N : usize > TryFrom < & mut [ T ] > for [ T ; N ]
where
T : Copy ,
{
type Error = TryFromSliceError ;
2023-05-25 18:24:27 -04:00
#[ inline ]
2021-11-20 21:40:41 +09:00
fn try_from ( slice : & mut [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
2021-11-21 11:01:31 +09:00
< Self > ::try_from ( & * slice )
2021-11-20 21:40:41 +09:00
}
}
2022-09-10 19:37:07 -07:00
/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
/// `slice.len() == N`.
///
/// ```
/// let bytes: [u8; 3] = [1, 0, 2];
///
/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
///
/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
/// ```
2019-07-25 18:06:26 +02:00
#[ stable(feature = " try_from " , since = " 1.34.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < ' a , T , const N : usize > TryFrom < & ' a [ T ] > for & ' a [ T ; N ] {
2019-07-25 18:06:26 +02:00
type Error = TryFromSliceError ;
2023-05-25 18:24:27 -04:00
#[ inline ]
2023-04-28 17:36:49 +00:00
fn try_from ( slice : & ' a [ T ] ) -> Result < & ' a [ T ; N ] , TryFromSliceError > {
2024-11-26 21:49:28 +01:00
slice . as_array ( ) . ok_or ( TryFromSliceError ( ( ) ) )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2022-09-10 19:37:07 -07:00
/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
/// `&mut [T]`. Succeeds if `slice.len() == N`.
///
/// ```
/// let mut bytes: [u8; 3] = [1, 0, 2];
///
/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
///
/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
/// ```
2019-07-25 18:06:26 +02:00
#[ stable(feature = " try_from " , since = " 1.34.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < ' a , T , const N : usize > TryFrom < & ' a mut [ T ] > for & ' a mut [ T ; N ] {
2019-07-25 18:06:26 +02:00
type Error = TryFromSliceError ;
2023-05-25 18:24:27 -04:00
#[ inline ]
2023-04-28 17:36:49 +00:00
fn try_from ( slice : & ' a mut [ T ] ) -> Result < & ' a mut [ T ; N ] , TryFromSliceError > {
2024-11-26 21:49:28 +01:00
slice . as_mut_array ( ) . ok_or ( TryFromSliceError ( ( ) ) )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2021-06-08 08:51:44 -07:00
/// The hash of an array is the same as that of the corresponding slice,
/// as required by the `Borrow` implementation.
///
/// ```
2021-06-24 01:30:08 -07:00
/// use std::hash::BuildHasher;
2021-06-08 08:51:44 -07:00
///
2023-10-13 02:44:19 -04:00
/// let b = std::hash::RandomState::new();
2021-06-08 08:51:44 -07:00
/// let a: [u8; 3] = [0xa8, 0x3c, 0x09];
/// let s: &[u8] = &[0xa8, 0x3c, 0x09];
2021-06-24 01:30:08 -07:00
/// assert_eq!(b.hash_one(a), b.hash_one(s));
2021-06-08 08:51:44 -07:00
/// ```
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < T : Hash , const N : usize > Hash for [ T ; N ] {
2019-07-25 18:06:26 +02:00
fn hash < H : hash ::Hasher > ( & self , state : & mut H ) {
Hash ::hash ( & self [ .. ] , state )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < T : fmt ::Debug , const N : usize > fmt ::Debug for [ T ; N ] {
2019-07-25 18:06:26 +02:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
fmt ::Debug ::fmt ( & & self [ .. ] , f )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < ' a , T , const N : usize > IntoIterator for & ' a [ T ; N ] {
2019-07-25 18:06:26 +02:00
type Item = & ' a T ;
type IntoIter = Iter < ' a , T > ;
2019-07-05 23:59:59 -07:00
2019-07-25 18:06:26 +02:00
fn into_iter ( self ) -> Iter < ' a , T > {
self . iter ( )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < ' a , T , const N : usize > IntoIterator for & ' a mut [ T ; N ] {
2019-07-25 18:06:26 +02:00
type Item = & ' a mut T ;
type IntoIter = IterMut < ' a , T > ;
2019-07-05 23:59:59 -07:00
2019-07-25 18:06:26 +02:00
fn into_iter ( self ) -> IterMut < ' a , T > {
self . iter_mut ( )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
}
2019-07-05 23:59:59 -07:00
2020-07-31 23:19:10 +03:00
#[ stable(feature = " index_trait_on_arrays " , since = " 1.50.0 " ) ]
2023-04-16 06:49:27 +00:00
impl < T , I , const N : usize > Index < I > for [ T ; N ]
2020-07-31 23:19:10 +03:00
where
2023-04-16 06:49:27 +00:00
[ T ] : Index < I > ,
2020-07-31 23:19:10 +03:00
{
type Output = < [ T ] as Index < I > > ::Output ;
#[ inline ]
fn index ( & self , index : I ) -> & Self ::Output {
Index ::index ( self as & [ T ] , index )
}
}
#[ stable(feature = " index_trait_on_arrays " , since = " 1.50.0 " ) ]
2023-04-16 06:49:27 +00:00
impl < T , I , const N : usize > IndexMut < I > for [ T ; N ]
2020-07-31 23:19:10 +03:00
where
2023-04-16 06:49:27 +00:00
[ T ] : IndexMut < I > ,
2020-07-31 23:19:10 +03:00
{
#[ inline ]
fn index_mut ( & mut self , index : I ) -> & mut Self ::Output {
IndexMut ::index_mut ( self as & mut [ T ] , index )
}
}
2024-03-06 10:28:56 +01:00
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < T : PartialOrd , const N : usize > PartialOrd for [ T ; N ] {
2019-07-25 18:06:26 +02:00
#[ inline ]
fn partial_cmp ( & self , other : & [ T ; N ] ) -> Option < Ordering > {
PartialOrd ::partial_cmp ( & & self [ .. ] , & & other [ .. ] )
2019-07-05 23:59:59 -07:00
}
2019-07-25 18:06:26 +02:00
#[ inline ]
fn lt ( & self , other : & [ T ; N ] ) -> bool {
PartialOrd ::lt ( & & self [ .. ] , & & other [ .. ] )
}
#[ inline ]
fn le ( & self , other : & [ T ; N ] ) -> bool {
PartialOrd ::le ( & & self [ .. ] , & & other [ .. ] )
}
#[ inline ]
fn ge ( & self , other : & [ T ; N ] ) -> bool {
PartialOrd ::ge ( & & self [ .. ] , & & other [ .. ] )
}
#[ inline ]
fn gt ( & self , other : & [ T ; N ] ) -> bool {
PartialOrd ::gt ( & & self [ .. ] , & & other [ .. ] )
}
}
2019-07-05 23:59:59 -07:00
2020-10-25 17:46:45 +08:00
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
2019-07-25 18:06:26 +02:00
#[ stable(feature = " rust1 " , since = " 1.0.0 " ) ]
2020-07-05 15:02:01 +03:00
impl < T : Ord , const N : usize > Ord for [ T ; N ] {
2019-07-25 18:06:26 +02:00
#[ inline ]
fn cmp ( & self , other : & [ T ; N ] ) -> Ordering {
Ord ::cmp ( & & self [ .. ] , & & other [ .. ] )
2019-07-05 23:59:59 -07:00
}
}
2021-11-08 15:51:56 -05:00
#[ stable(feature = " copy_clone_array_lib " , since = " 1.58.0 " ) ]
2021-06-05 17:17:35 -04:00
impl < T : Copy , const N : usize > Copy for [ T ; N ] { }
2021-11-08 15:51:56 -05:00
#[ stable(feature = " copy_clone_array_lib " , since = " 1.58.0 " ) ]
2021-06-05 17:17:35 -04:00
impl < T : Clone , const N : usize > Clone for [ T ; N ] {
2021-11-08 15:51:56 -05:00
#[ inline ]
2021-06-05 17:17:35 -04:00
fn clone ( & self ) -> Self {
2021-11-09 21:43:20 -08:00
SpecArrayClone ::clone ( self )
2021-06-05 17:17:35 -04:00
}
2021-11-08 15:51:56 -05:00
#[ inline ]
2021-06-05 17:17:35 -04:00
fn clone_from ( & mut self , other : & Self ) {
self . clone_from_slice ( other ) ;
}
}
2021-11-09 21:43:20 -08:00
trait SpecArrayClone : Clone {
fn clone < const N : usize > ( array : & [ Self ; N ] ) -> [ Self ; N ] ;
}
impl < T : Clone > SpecArrayClone for T {
2021-11-10 11:57:14 -08:00
#[ inline ]
2021-11-09 21:43:20 -08:00
default fn clone < const N : usize > ( array : & [ T ; N ] ) -> [ T ; N ] {
2023-02-03 03:27:51 -08:00
from_trusted_iterator ( array . iter ( ) . cloned ( ) )
2021-11-09 21:43:20 -08:00
}
}
impl < T : Copy > SpecArrayClone for T {
2021-11-10 11:57:14 -08:00
#[ inline ]
2021-11-09 21:43:20 -08:00
fn clone < const N : usize > ( array : & [ T ; N ] ) -> [ T ; N ] {
* array
}
}
2020-11-04 01:48:28 +01:00
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
// require Default to be implemented, and having different impl blocks for
2021-03-08 20:28:30 +05:30
// different numbers isn't supported yet.
2015-08-14 10:11:19 -07:00
macro_rules ! array_impl_default {
{ $n :expr , $t :ident $( $ts :ident ) * } = > {
#[ stable(since = " 1.4.0 " , feature = " array_default " ) ]
2023-04-16 06:49:27 +00:00
impl < T > Default for [ T ; $n ] where T : Default {
2015-08-14 10:11:19 -07:00
fn default ( ) -> [ T ; $n ] {
[ $t ::default ( ) , $( $ts ::default ( ) ) , * ]
}
}
array_impl_default! { ( $n - 1 ) , $( $ts ) * }
} ;
{ $n :expr , } = > {
#[ stable(since = " 1.4.0 " , feature = " array_default " ) ]
2023-04-16 06:49:27 +00:00
impl < T > Default for [ T ; $n ] {
2015-08-14 10:11:19 -07:00
fn default ( ) -> [ T ; $n ] { [ ] }
}
} ;
}
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 }
2020-08-06 07:40:06 +00:00
impl < T , const N : usize > [ T ; N ] {
2020-08-08 23:20:28 +00:00
/// Returns an array of the same size as `self`, with function `f` applied to each element
/// in order.
2020-08-06 07:40:06 +00:00
///
2021-07-30 00:08:48 +02:00
/// If you don't necessarily need a new fixed-size array, consider using
/// [`Iterator::map`] instead.
///
///
/// # Note on performance and stack usage
///
/// Unfortunately, usages of this method are currently not always optimized
/// as well as they could be. This mainly concerns large arrays, as mapping
/// over small arrays seem to be optimized just fine. Also note that in
/// debug mode (i.e. without any optimizations), this method can use a lot
/// of stack space (a few times the size of the array or more).
///
/// Therefore, in performance-critical code, try to avoid using this method
/// on large arrays or check the emitted code. Also try to avoid chained
/// maps (e.g. `arr.map(...).map(...)`).
///
/// In many cases, you can instead use [`Iterator::map`] by calling `.iter()`
/// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you
/// really need a new array of the same size as the result. Rust's lazy
/// iterators tend to get optimized very well.
///
///
2020-08-06 07:40:06 +00:00
/// # Examples
2020-08-07 06:00:52 +00:00
///
2020-08-06 07:40:06 +00:00
/// ```
2020-08-06 23:36:50 +00:00
/// let x = [1, 2, 3];
2020-08-06 07:40:06 +00:00
/// let y = x.map(|v| v + 1);
2020-08-06 23:36:50 +00:00
/// assert_eq!(y, [2, 3, 4]);
2020-08-07 06:00:52 +00:00
///
/// let x = [1, 2, 3];
/// let mut temp = 0;
/// let y = x.map(|v| { temp += 1; v * temp });
/// assert_eq!(y, [1, 4, 9]);
2020-08-08 23:20:28 +00:00
///
/// let x = ["Ferris", "Bueller's", "Day", "Off"];
/// let y = x.map(|v| v.len());
/// assert_eq!(y, [6, 9, 3, 3]);
2020-08-06 07:40:06 +00:00
/// ```
2021-07-15 16:27:08 -07:00
#[ stable(feature = " array_map " , since = " 1.55.0 " ) ]
2021-02-14 14:42:47 +01:00
pub fn map < F , U > ( self , f : F ) -> [ U ; N ]
2020-08-06 07:40:06 +00:00
where
2020-08-06 23:36:50 +00:00
F : FnMut ( T ) -> U ,
2020-08-06 07:40:06 +00:00
{
2023-02-03 03:27:51 -08:00
self . try_map ( NeverShortCircuit ::wrap_mut_1 ( f ) ) . 0
2020-08-06 07:40:06 +00:00
}
2020-08-30 20:22:09 +02:00
2021-11-26 23:09:34 -08:00
/// A fallible function `f` applied to each element on array `self` in order to
/// return an array the same size as `self` or the first error encountered.
///
/// The return type of this function depends on the return type of the closure.
2022-12-15 14:05:01 +01:00
/// If you return `Result<T, E>` from the closure, you'll get a `Result<[T; N], E>`.
2021-11-26 23:09:34 -08:00
/// If you return `Option<T>` from the closure, you'll get an `Option<[T; N]>`.
///
/// # Examples
///
/// ```
2024-04-21 18:41:45 +02:00
/// #![feature(array_try_map)]
///
2021-11-26 23:09:34 -08:00
/// let a = ["1", "2", "3"];
/// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
/// assert_eq!(b, [2, 3, 4]);
///
/// let a = ["1", "2a", "3"];
/// let b = a.try_map(|v| v.parse::<u32>());
/// assert!(b.is_err());
///
2024-02-18 21:29:24 +01:00
/// use std::num::NonZero;
2024-04-21 18:41:45 +02:00
///
2021-11-26 23:09:34 -08:00
/// let z = [1, 2, 0, 3, 4];
2024-02-18 21:29:24 +01:00
/// assert_eq!(z.try_map(NonZero::new), None);
2024-04-21 18:41:45 +02:00
///
2021-11-26 23:09:34 -08:00
/// let a = [1, 2, 3];
2024-02-18 21:29:24 +01:00
/// let b = a.try_map(NonZero::new);
/// let c = b.map(|x| x.map(NonZero::get));
2021-11-26 23:09:34 -08:00
/// assert_eq!(c, Some(a));
/// ```
#[ unstable(feature = " array_try_map " , issue = " 79711 " ) ]
2024-06-10 17:55:28 -07:00
pub fn try_map < R > ( self , f : impl FnMut ( T ) -> R ) -> ChangeOutputType < R , [ R ::Output ; N ] >
2021-11-26 23:09:34 -08:00
where
2024-06-10 17:55:28 -07:00
R : Try < Residual : Residual < [ R ::Output ; N ] > > ,
2021-11-26 23:09:34 -08:00
{
2023-02-03 03:27:51 -08:00
drain_array_with ( self , | iter | try_from_trusted_iterator ( iter . map ( f ) ) )
2021-11-26 23:09:34 -08:00
}
2020-08-30 20:22:09 +02:00
/// Returns a slice containing the entire array. Equivalent to `&s[..]`.
2021-08-26 05:27:39 -04:00
#[ stable(feature = " array_as_slice " , since = " 1.57.0 " ) ]
2021-11-17 21:08:16 -05:00
#[ rustc_const_stable(feature = " array_as_slice " , since = " 1.57.0 " ) ]
2021-08-26 05:27:39 -04:00
pub const fn as_slice ( & self ) -> & [ T ] {
2020-08-30 20:22:09 +02:00
self
}
/// Returns a mutable slice containing the entire array. Equivalent to
/// `&mut s[..]`.
2021-08-26 05:27:39 -04:00
#[ stable(feature = " array_as_slice " , since = " 1.57.0 " ) ]
2024-11-22 09:44:08 +01:00
#[ rustc_const_unstable(feature = " const_array_as_mut_slice " , issue = " 133333 " ) ]
pub const fn as_mut_slice ( & mut self ) -> & mut [ T ] {
2020-08-30 20:22:09 +02:00
self
}
2020-08-13 00:19:53 +02:00
/// Borrows each element and returns an array of references with the same
/// size as `self`.
///
///
/// # Example
///
/// ```
/// 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
2021-03-08 11:49:26 +05:30
/// [`map`](#method.map). This way, you can avoid moving the original
2021-08-29 12:29:43 -07:00
/// array if its elements are not [`Copy`].
2020-08-13 00:19:53 +02:00
///
/// ```
/// 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);
/// ```
2024-02-03 16:37:58 -05:00
#[ stable(feature = " array_methods " , since = " 1.77.0 " ) ]
2024-11-21 12:16:00 +01:00
#[ rustc_const_unstable(feature = " const_array_each_ref " , issue = " 133289 " ) ]
pub const fn each_ref ( & self ) -> [ & T ; N ] {
let mut buf = [ null ::< T > ( ) ; N ] ;
// 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.
let mut i = 0 ;
while i < N {
buf [ i ] = & raw const self [ i ] ;
i + = 1 ;
}
// SAFETY: `*const T` has the same layout as `&T`, and we've also initialised each pointer as a valid reference.
unsafe { transmute_unchecked ( buf ) }
2020-08-13 00:19:53 +02:00
}
/// Borrows each element mutably and returns an array of mutable references
/// with the same size as `self`.
///
///
/// # Example
///
/// ```
///
/// 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]);
/// ```
2024-02-03 16:37:58 -05:00
#[ stable(feature = " array_methods " , since = " 1.77.0 " ) ]
2024-11-21 12:16:00 +01:00
#[ rustc_const_unstable(feature = " const_array_each_ref " , issue = " 133289 " ) ]
pub const fn each_mut ( & mut self ) -> [ & mut T ; N ] {
let mut buf = [ null_mut ::< T > ( ) ; N ] ;
// 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.
let mut i = 0 ;
while i < N {
buf [ i ] = & raw mut self [ i ] ;
i + = 1 ;
}
// SAFETY: `*mut T` has the same layout as `&mut T`, and we've also initialised each pointer as a valid reference.
unsafe { transmute_unchecked ( buf ) }
2021-02-14 14:42:47 +01:00
}
2021-03-17 17:23:09 +01:00
/// Divides one array reference into two at an index.
///
/// The first will contain all indices from `[0, M)` (excluding
/// the index `M` itself) and the second will contain all
/// indices from `[M, N)` (excluding the index `N` itself).
///
/// # Panics
///
/// Panics if `M > N`.
///
/// # Examples
///
/// ```
/// #![feature(split_array)]
///
/// let v = [1, 2, 3, 4, 5, 6];
///
/// {
/// let (left, right) = v.split_array_ref::<0>();
/// assert_eq!(left, &[]);
/// assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
/// }
///
/// {
/// let (left, right) = v.split_array_ref::<2>();
/// assert_eq!(left, &[1, 2]);
/// assert_eq!(right, &[3, 4, 5, 6]);
/// }
///
/// {
/// let (left, right) = v.split_array_ref::<6>();
/// assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
/// assert_eq!(right, &[]);
/// }
/// ```
#[ unstable(
feature = " split_array " ,
reason = " return type should have array as 2nd element " ,
issue = " 90091 "
) ]
#[ inline ]
pub fn split_array_ref < const M : usize > ( & self ) -> ( & [ T ; M ] , & [ T ] ) {
2023-11-03 20:38:30 -05:00
( & self [ .. ] ) . split_first_chunk ::< M > ( ) . unwrap ( )
2021-03-17 17:23:09 +01:00
}
/// Divides one mutable array reference into two at an index.
///
/// The first will contain all indices from `[0, M)` (excluding
/// the index `M` itself) and the second will contain all
/// indices from `[M, N)` (excluding the index `N` itself).
///
/// # Panics
///
/// Panics if `M > N`.
///
/// # Examples
///
/// ```
/// #![feature(split_array)]
///
/// let mut v = [1, 0, 3, 0, 5, 6];
/// let (left, right) = v.split_array_mut::<2>();
/// assert_eq!(left, &mut [1, 0][..]);
/// assert_eq!(right, &mut [3, 0, 5, 6]);
/// left[1] = 2;
/// right[1] = 4;
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
/// ```
#[ unstable(
feature = " split_array " ,
reason = " return type should have array as 2nd element " ,
issue = " 90091 "
) ]
#[ inline ]
pub fn split_array_mut < const M : usize > ( & mut self ) -> ( & mut [ T ; M ] , & mut [ T ] ) {
2023-11-03 20:38:30 -05:00
( & mut self [ .. ] ) . split_first_chunk_mut ::< M > ( ) . unwrap ( )
2021-03-17 17:23:09 +01:00
}
2021-12-04 10:32:09 +01:00
/// Divides one array reference into two at an index from the end.
///
/// The first will contain all indices from `[0, N - M)` (excluding
/// the index `N - M` itself) and the second will contain all
/// indices from `[N - M, N)` (excluding the index `N` itself).
///
/// # Panics
///
/// Panics if `M > N`.
///
/// # Examples
///
/// ```
/// #![feature(split_array)]
///
/// let v = [1, 2, 3, 4, 5, 6];
///
/// {
/// let (left, right) = v.rsplit_array_ref::<0>();
/// assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
/// assert_eq!(right, &[]);
/// }
///
/// {
/// let (left, right) = v.rsplit_array_ref::<2>();
/// assert_eq!(left, &[1, 2, 3, 4]);
/// assert_eq!(right, &[5, 6]);
/// }
///
/// {
/// let (left, right) = v.rsplit_array_ref::<6>();
/// assert_eq!(left, &[]);
/// assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
/// }
/// ```
#[ unstable(
feature = " split_array " ,
reason = " return type should have array as 2nd element " ,
issue = " 90091 "
) ]
#[ inline ]
pub fn rsplit_array_ref < const M : usize > ( & self ) -> ( & [ T ] , & [ T ; M ] ) {
2023-11-03 20:38:30 -05:00
( & self [ .. ] ) . split_last_chunk ::< M > ( ) . unwrap ( )
2021-12-04 10:32:09 +01:00
}
/// Divides one mutable array reference into two at an index from the end.
///
/// The first will contain all indices from `[0, N - M)` (excluding
/// the index `N - M` itself) and the second will contain all
/// indices from `[N - M, N)` (excluding the index `N` itself).
///
/// # Panics
///
/// Panics if `M > N`.
///
/// # Examples
///
/// ```
/// #![feature(split_array)]
///
/// let mut v = [1, 0, 3, 0, 5, 6];
/// let (left, right) = v.rsplit_array_mut::<4>();
/// assert_eq!(left, &mut [1, 0]);
/// assert_eq!(right, &mut [3, 0, 5, 6][..]);
/// left[1] = 2;
/// right[1] = 4;
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
/// ```
#[ unstable(
feature = " split_array " ,
reason = " return type should have array as 2nd element " ,
issue = " 90091 "
) ]
#[ inline ]
pub fn rsplit_array_mut < const M : usize > ( & mut self ) -> ( & mut [ T ] , & mut [ T ; M ] ) {
2023-11-03 20:38:30 -05:00
( & mut self [ .. ] ) . split_last_chunk_mut ::< M > ( ) . unwrap ( )
2021-12-04 10:32:09 +01:00
}
2021-02-14 14:42:47 +01:00
}
2023-02-03 03:27:51 -08:00
/// Populate an array from the first `N` elements of `iter`
2021-02-14 14:42:47 +01:00
///
2023-02-03 03:27:51 -08:00
/// # Panics
2021-02-14 14:42:47 +01:00
///
2023-02-03 03:27:51 -08:00
/// If the iterator doesn't actually have enough items.
2021-02-14 14:42:47 +01:00
///
2023-02-03 03:27:51 -08:00
/// By depending on `TrustedLen`, however, we can do that check up-front (where
/// it easily optimizes away) so it doesn't impact the loop that fills the array.
#[ inline ]
fn from_trusted_iterator < T , const N : usize > ( iter : impl UncheckedIterator < Item = T > ) -> [ T ; N ] {
try_from_trusted_iterator ( iter . map ( NeverShortCircuit ) ) . 0
2021-02-14 14:42:47 +01:00
}
2023-02-03 03:27:51 -08:00
#[ inline ]
fn try_from_trusted_iterator < T , R , const N : usize > (
iter : impl UncheckedIterator < Item = R > ,
) -> ChangeOutputType < R , [ T ; N ] >
2021-09-30 07:49:32 -03:00
where
2023-02-03 03:27:51 -08:00
R : Try < Output = T > ,
R ::Residual : Residual < [ T ; N ] > ,
2021-09-30 07:49:32 -03:00
{
2023-02-03 03:27:51 -08:00
assert! ( iter . size_hint ( ) . 0 > = N ) ;
fn next < T > ( mut iter : impl UncheckedIterator < Item = T > ) -> impl FnMut ( usize ) -> T {
move | _ | {
// SAFETY: We know that `from_fn` will call this at most N times,
// and we checked to ensure that we have at least that many items.
unsafe { iter . next_unchecked ( ) }
}
2021-09-30 14:19:56 +02:00
}
2023-02-03 03:27:51 -08:00
try_from_fn ( next ( iter ) )
2021-09-30 07:49:32 -03:00
}
2023-02-03 03:27:51 -08:00
/// Version of [`try_from_fn`] using a passed-in slice in order to avoid
/// needing to monomorphize for every array length.
2021-02-14 14:42:47 +01:00
///
2023-02-03 03:27:51 -08:00
/// This takes a generator rather than an iterator so that *at the type level*
/// it never needs to worry about running out of items. When combined with
/// an infallible `Try` type, that means the loop canonicalizes easily, allowing
/// it to optimize well.
2021-02-14 14:42:47 +01:00
///
2023-02-03 03:27:51 -08:00
/// It would be *possible* to unify this and [`iter_next_chunk_erased`] into one
/// function that does the union of both things, but last time it was that way
/// it resulted in poor codegen from the "are there enough source items?" checks
/// not optimizing away. So if you give it a shot, make sure to watch what
/// happens in the codegen tests.
2022-06-21 08:57:02 +02:00
#[ inline ]
2023-02-03 03:27:51 -08:00
fn try_from_fn_erased < T , R > (
2023-02-02 22:15:23 -08:00
buffer : & mut [ MaybeUninit < T > ] ,
2023-02-03 03:27:51 -08:00
mut generator : impl FnMut ( usize ) -> R ,
) -> ControlFlow < R ::Residual >
2021-02-14 14:42:47 +01:00
where
2023-02-03 03:27:51 -08:00
R : Try < Output = T > ,
2021-02-14 14:42:47 +01:00
{
2023-02-02 22:15:23 -08:00
let mut guard = Guard { array_mut : buffer , initialized : 0 } ;
2021-02-14 14:42:47 +01:00
2023-02-03 03:27:51 -08:00
while guard . initialized < guard . array_mut . len ( ) {
let item = generator ( guard . initialized ) . branch ( ) ? ;
2022-06-21 08:57:02 +02:00
2023-02-03 03:27:51 -08:00
// SAFETY: The loop condition ensures we have space to push the item
unsafe { guard . push_unchecked ( item ) } ;
2020-08-13 00:19:53 +02:00
}
2021-02-14 14:42:47 +01:00
2022-06-21 08:57:02 +02:00
mem ::forget ( guard ) ;
2023-02-03 03:27:51 -08:00
ControlFlow ::Continue ( ( ) )
2022-06-21 08:57:02 +02:00
}
2022-11-08 00:13:26 +01:00
/// Panic guard for incremental initialization of arrays.
///
/// Disarm the guard with `mem::forget` once the array has been initialized.
///
/// # Safety
///
/// All write accesses to this structure are unsafe and must maintain a correct
/// count of `initialized` elements.
///
/// To minimize indirection fields are still pub but callers should at least use
/// `push_unchecked` to signal that something unsafe is going on.
2023-02-03 03:27:51 -08:00
struct Guard < ' a , T > {
2022-11-08 00:13:26 +01:00
/// The array to be initialized.
2023-02-02 22:15:23 -08:00
pub array_mut : & ' a mut [ MaybeUninit < T > ] ,
2022-11-08 00:13:26 +01:00
/// The number of items that have been initialized so far.
2022-10-23 19:17:41 +02:00
pub initialized : usize ,
}
2023-02-02 22:15:23 -08:00
impl < T > Guard < '_ , T > {
2022-11-08 00:13:26 +01:00
/// Adds an item to the array and updates the initialized item counter.
///
/// # Safety
///
/// No more than N elements must be initialized.
#[ inline ]
pub unsafe fn push_unchecked ( & mut self , item : T ) {
// SAFETY: If `initialized` was correct before and the caller does not
// invoke this method more than N times then writes will be in-bounds
// and slots will not be initialized more than once.
unsafe {
self . array_mut . get_unchecked_mut ( self . initialized ) . write ( item ) ;
self . initialized = self . initialized . unchecked_add ( 1 ) ;
}
}
}
2023-02-02 22:15:23 -08:00
impl < T > Drop for Guard < '_ , T > {
2024-08-09 11:10:30 +08:00
#[ inline ]
2022-10-23 19:17:41 +02:00
fn drop ( & mut self ) {
2023-02-02 22:15:23 -08:00
debug_assert! ( self . initialized < = self . array_mut . len ( ) ) ;
2022-10-23 19:17:41 +02:00
// SAFETY: this slice will contain only initialized objects.
unsafe {
2024-08-18 19:50:41 -04:00
self . array_mut . get_unchecked_mut ( .. self . initialized ) . assume_init_drop ( ) ;
2022-10-23 19:17:41 +02:00
}
}
}
2023-02-02 22:15:23 -08:00
/// 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`].
2022-06-21 08:57:02 +02:00
#[ inline ]
2023-02-02 22:15:23 -08:00
pub ( crate ) fn iter_next_chunk < T , const N : usize > (
iter : & mut impl Iterator < Item = T > ,
) -> Result < [ T ; N ] , IntoIter < T , N > > {
2024-05-12 21:37:53 -07:00
let mut array = [ const { MaybeUninit ::uninit ( ) } ; N ] ;
2023-02-03 03:27:51 -08:00
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 ]
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 ) } ;
2023-02-02 22:15:23 -08:00
}
2023-02-03 03:27:51 -08:00
mem ::forget ( guard ) ;
Ok ( ( ) )
2020-08-06 07:40:06 +00:00
}