Skip to content

Commit 28e84e4

Browse files
authored
Rollup merge of rust-lang#87636 - Kixiron:unzip-option, r=scottmcm
Added the `Option::unzip()` method * Adds the `Option::unzip()` method to turn an `Option<(T, U)>` into `(Option<T>, Option<U>)` under the `unzip_option` feature * Adds tests for both `Option::unzip()` and `Option::zip()`, I noticed that `.zip()` didn't have any * Adds `#[inline]` to a few of `Option`'s methods that were missing it
2 parents 33186e4 + ab2c590 commit 28e84e4

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

library/core/src/option.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,33 @@ impl<T> Option<T> {
13991399
}
14001400
}
14011401

1402+
impl<T, U> Option<(T, U)> {
1403+
/// Unzips an option containing a tuple of two options
1404+
///
1405+
/// If `self` is `Some((a, b))` this method returns `(Some(a), Some(b))`.
1406+
/// Otherwise, `(None, None)` is returned.
1407+
///
1408+
/// # Examples
1409+
///
1410+
/// ```
1411+
/// #![feature(unzip_option)]
1412+
///
1413+
/// let x = Some((1, "hi"));
1414+
/// let y = None::<(u8, u32)>;
1415+
///
1416+
/// assert_eq!(x.unzip(), (Some(1), Some("hi")));
1417+
/// assert_eq!(y.unzip(), (None, None));
1418+
/// ```
1419+
#[inline]
1420+
#[unstable(feature = "unzip_option", issue = "87800", reason = "recently added")]
1421+
pub const fn unzip(self) -> (Option<T>, Option<U>) {
1422+
match self {
1423+
Some((a, b)) => (Some(a), Some(b)),
1424+
None => (None, None),
1425+
}
1426+
}
1427+
}
1428+
14021429
impl<T: Copy> Option<&T> {
14031430
/// Maps an `Option<&T>` to an `Option<T>` by copying the contents of the
14041431
/// option.

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#![feature(slice_group_by)]
6969
#![feature(trusted_random_access)]
7070
#![feature(unsize)]
71+
#![feature(unzip_option)]
7172
#![deny(unsafe_op_in_unsafe_fn)]
7273

7374
extern crate test;

library/core/tests/option.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -399,11 +399,43 @@ fn test_unwrap_drop() {
399399
}
400400

401401
#[test]
402-
pub fn option_ext() {
402+
fn option_ext() {
403403
let thing = "{{ f }}";
404404
let f = thing.find("{{");
405405

406406
if f.is_none() {
407407
println!("None!");
408408
}
409409
}
410+
411+
#[test]
412+
fn zip_options() {
413+
let x = Some(10);
414+
let y = Some("foo");
415+
let z: Option<usize> = None;
416+
417+
assert_eq!(x.zip(y), Some((10, "foo")));
418+
assert_eq!(x.zip(z), None);
419+
assert_eq!(z.zip(x), None);
420+
}
421+
422+
#[test]
423+
fn unzip_options() {
424+
let x = Some((10, "foo"));
425+
let y = None::<(bool, i32)>;
426+
427+
assert_eq!(x.unzip(), (Some(10), Some("foo")));
428+
assert_eq!(y.unzip(), (None, None));
429+
}
430+
431+
#[test]
432+
fn zip_unzip_roundtrip() {
433+
let x = Some(10);
434+
let y = Some("foo");
435+
436+
let z = x.zip(y);
437+
assert_eq!(z, Some((10, "foo")));
438+
439+
let a = z.unzip();
440+
assert_eq!(a, (x, y));
441+
}

0 commit comments

Comments
 (0)