Skip to content

Commit 3ca91ad

Browse files
committed
Add [Option<T>; N]::transpose
1 parent 702987f commit 3ca91ad

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

library/core/src/option.rs

+41
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@
557557
#![stable(feature = "rust1", since = "1.0.0")]
558558

559559
use crate::iter::{self, FusedIterator, TrustedLen};
560+
use crate::mem::MaybeUninit;
560561
use crate::ops::{self, ControlFlow, Deref, DerefMut};
561562
use crate::panicking::{panic, panic_display};
562563
use crate::pin::Pin;
@@ -2545,3 +2546,43 @@ impl<T> Option<Option<T>> {
25452546
}
25462547
}
25472548
}
2549+
2550+
impl<T, const N: usize> [Option<T>; N] {
2551+
/// Transposes a `[Option<T>; N]` into a `Option<[T; N]>`.
2552+
///
2553+
/// This will return `Some` only if every input element is `Some`. If any element is `None`,
2554+
/// all values are dropped and this returns `None`.
2555+
///
2556+
/// # Examples
2557+
///
2558+
/// ```
2559+
/// #![feature(option_array_transpose)]
2560+
///
2561+
/// let data = [Some(0); 1000];
2562+
/// let data: Option<[u8; 1000]> = data.transpose();
2563+
/// assert_eq!(data, Some([0; 1000]));
2564+
///
2565+
/// let data = [Some(0), None];
2566+
/// let data: Option<[u8; 2]> = data.transpose();
2567+
/// assert_eq!(data, None);
2568+
/// ```
2569+
#[inline]
2570+
#[unstable(feature = "option_array_transpose", issue = "130828")]
2571+
pub fn transpose(self) -> Option<[T; N]> {
2572+
let mut array: MaybeUninit<[T; N]> = MaybeUninit::uninit();
2573+
let array_mut = array.as_mut_ptr();
2574+
2575+
for (i, e) in self.into_iter().enumerate() {
2576+
match e {
2577+
// SAFETY: `i` is always inbounds
2578+
Some(e) => unsafe {
2579+
*(*array_mut).get_unchecked_mut(i) = e;
2580+
},
2581+
None => return None,
2582+
}
2583+
}
2584+
2585+
// SAFETY: All the elements have been initialized
2586+
Some(unsafe { array.assume_init() })
2587+
}
2588+
}

0 commit comments

Comments
 (0)