From bc4ce79764f6519ee9f1469fb3fddcc3f70b8e14 Mon Sep 17 00:00:00 2001 From: Chase Wilson Date: Fri, 30 Jul 2021 13:11:25 -0500 Subject: [PATCH 1/4] Added the `Option::unzip()` method --- library/core/src/option.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d4e9c384f9302..57553865bd015 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1399,6 +1399,31 @@ impl Option { } } +impl Option<(T, U)> { + /// Unzips an option containing a tuple of two options + /// + /// If `self` is `Some((a, b))` this method returns `(Some(a), Some(b))`. + /// Otherwise, `(None, None)` is returned. + /// + /// # Examples + /// + /// ``` + /// let x = Some((1, "hi")); + /// let y = None::<(u8, u32)>; + /// + /// assert_eq!(x.unzip(), (Some(1), Some("hi"))); + /// assert_eq!(y.unzip(), (None, None)); + /// ``` + #[inline] + #[unstable(feature = "unzip_option", issue = "none", reason = "recently added")] + pub const fn unzip(self) -> (Option, Option) { + match self { + Some((a, b)) => (Some(a), Some(b)), + None => (None, None), + } + } +} + impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by copying the contents of the /// option. From eea3520a8fc1c4a03626ee4f9d74b6d9833db54c Mon Sep 17 00:00:00 2001 From: Chase Wilson Date: Fri, 30 Jul 2021 13:13:59 -0500 Subject: [PATCH 2/4] Added some basic tests for `Option::unzip()` and `Option::zip()` (I noticed that zip had no tests) --- library/core/tests/option.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 88ea15a3b33fa..cd8fdebe36a05 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -399,7 +399,7 @@ fn test_unwrap_drop() { } #[test] -pub fn option_ext() { +fn option_ext() { let thing = "{{ f }}"; let f = thing.find("{{"); @@ -407,3 +407,35 @@ pub fn option_ext() { println!("None!"); } } + +#[test] +fn zip_options() { + let x = Some(10); + let y = Some("foo"); + let z: Option = None; + + assert_eq!(x.zip(y), Some((10, "foo"))); + assert_eq!(x.zip(z), None); + assert_eq!(z.zip(x), None); +} + +#[test] +fn unzip_options() { + let x = Some((10, "foo")); + let y = None::<(bool, i32)>; + + assert_eq!(x.unzip(), (Some(10), Some("foo"))); + assert_eq!(y.unzip(), (None, None)); +} + +#[test] +fn zip_unzip_roundtrip() { + let x = Some(10); + let y = Some("foo"); + + let z = x.zip(y); + assert_eq!(z, Some((10, "foo"))); + + let a = z.unzip(); + assert_eq!(a, (x, y)); +} From 9d8081e8b6e4082ed06bd984cd59ccf39741c9b7 Mon Sep 17 00:00:00 2001 From: Chase Wilson Date: Sat, 31 Jul 2021 18:16:34 -0500 Subject: [PATCH 3/4] Enabled unzip_option feature for core tests & unzip docs --- library/core/src/option.rs | 2 ++ library/core/tests/lib.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 57553865bd015..d65915cdc71e0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1408,6 +1408,8 @@ impl Option<(T, U)> { /// # Examples /// /// ``` + /// #![feature(unzip_option)] + /// /// let x = Some((1, "hi")); /// let y = None::<(u8, u32)>; /// diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c7756a503c3e9..cc3527f98ec65 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -66,6 +66,7 @@ #![feature(slice_group_by)] #![feature(trusted_random_access)] #![feature(unsize)] +#![feature(unzip_option)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; From ab2c5902ca404cb21fc9fa8bd6f5c52f33d92949 Mon Sep 17 00:00:00 2001 From: Chase Wilson Date: Thu, 5 Aug 2021 12:44:22 -0500 Subject: [PATCH 4/4] Added tracking issue to unstable attribute --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d65915cdc71e0..3f9f04606b36a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1417,7 +1417,7 @@ impl Option<(T, U)> { /// assert_eq!(y.unzip(), (None, None)); /// ``` #[inline] - #[unstable(feature = "unzip_option", issue = "none", reason = "recently added")] + #[unstable(feature = "unzip_option", issue = "87800", reason = "recently added")] pub const fn unzip(self) -> (Option, Option) { match self { Some((a, b)) => (Some(a), Some(b)),