From 2c7a4ba2527b177018bf8b00791e89cf21843b2b Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 25 Sep 2024 13:23:06 +0200 Subject: [PATCH] Add `[Option; N]::transpose` --- library/core/src/option.rs | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 30c667e2494b2..0eff3df6a3f77 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -557,6 +557,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FusedIterator, TrustedLen}; +use crate::mem::MaybeUninit; use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::panicking::{panic, panic_display}; use crate::pin::Pin; @@ -2545,3 +2546,41 @@ impl Option> { } } } + +impl [Option; N] { + /// Transposes a `[Option; N]` into a `Option<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_array_transpose)] + /// # use std::option::Option; + /// + /// let data = [Some(0); 1000]; + /// let data: Option<[u8; 1000]> = data.transpose(); + /// assert_eq!(data, Some([0; 1000])); + /// + /// let data = [Some(0), None]; + /// let data: Option<[u8; 2]> = data.transpose(); + /// assert_eq!(data, None); + /// ``` + #[inline] + #[unstable(feature = "option_array_transpose", issue = "130828")] + pub fn transpose(self) -> Option<[T; N]> { + let mut array: MaybeUninit<[T; N]> = MaybeUninit::uninit(); + let array_mut = array.as_mut_ptr(); + + for (i, e) in self.into_iter().enumerate() { + match e { + // SAFETY: `i` is always inbounds + Some(e) => unsafe { + *(*array_mut).get_unchecked_mut(i) = e; + }, + None => return None, + } + } + + // SAFETY: All the elements have been initialized + Some(unsafe { array.assume_init() }) + } +}