From d369c84fe96f3b0c04a00bdec968f591de745bbf Mon Sep 17 00:00:00 2001 From: cairolover Date: Thu, 26 Dec 2024 16:33:07 +0100 Subject: [PATCH 1/5] feat(corelib): Result iterator --- corelib/src/result.cairo | 46 ++++++++++++++++++++++++++++++ corelib/src/test/result_test.cairo | 15 ++++++++++ 2 files changed, 61 insertions(+) diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index 87ef397f303..410b0372019 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -206,6 +206,8 @@ use crate::array::{ArrayTrait, SpanTrait}; #[allow(unused_imports)] use crate::serde::Serde; +#[allow(unused_imports)] +use crate::iter::{IntoIterator, Iterator}; /// The type used for returning and propagating errors. It is an enum with the variants `Ok: T`, /// representing success and containing a value, and `Err: E`, representing error and containing an @@ -686,3 +688,47 @@ pub impl ResultTraitImpl of ResultTrait { } } } + +/// An iterator over the value in a [`Ok`] variant of a [`Result`]. +/// +/// The iterator yields one value if the result is [`Ok`], otherwise none. +/// +/// This struct is created by the [`into_iter`] method on [`Result`] (provided by the +/// [`IntoIterator`] trait). +/// +/// [`into_iter`]: IntoIterator::into_iter +#[derive(Drop)] +pub struct ResultIter { + inner: Option, +} + +impl ResultIterator> of Iterator> { + type Item = T; + fn next(ref self: ResultIter) -> Option { + self.inner + } +} + +impl ResultIntoIterator, +Destruct, +Destruct> of IntoIterator> { + type IntoIter = ResultIter; + + /// Returns a consuming iterator over the possibly contained value. + /// + /// The iterator yields one value if the result is [`Result::Ok`], otherwise none. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Result::Ok(5); + /// let mut x_iter = x.into_iter(); + /// assert!(x_iter.next() == Option::Some(5)); + /// + /// let x: Result = Result::Err("nothing!"); + /// let mut x_iter = x.into_iter(); + /// assert!(x_iter.next() == Option::None); + /// ``` + #[inline] + fn into_iter(self: Result) -> ResultIter { + ResultIter { inner: self.ok() } + } +} diff --git a/corelib/src/test/result_test.cairo b/corelib/src/test/result_test.cairo index e54aec921c9..fee1947b1ed 100644 --- a/corelib/src/test/result_test.cairo +++ b/corelib/src/test/result_test.cairo @@ -1,4 +1,5 @@ use crate::result::{Result, ResultTraitImpl}; +use crate::iter::{IntoIterator, Iterator}; #[test] fn test_result_ok_expect() { @@ -312,3 +313,17 @@ fn test_result_err_map_err() { let x: Result = Result::Err(13); assert!(x.map_err(stringify) == Result::Err("error code: 13")); } + +#[test] +fn test_result_ok_iter_next() { + let x: Result = Result::Ok(5); + let mut x_iter = x.into_iter(); + assert!(x_iter.next() == Option::Some(5)); +} + +#[test] +fn test_result_err_iter_next() { + let x: Result = Result::Err("nothing!"); + let mut x_iter = x.into_iter(); + assert!(x_iter.next() == Option::None); +} From 35187ea615ecc7ff99bdca5fcdb36eb45a903c78 Mon Sep 17 00:00:00 2001 From: cairolover Date: Thu, 26 Dec 2024 16:58:24 +0100 Subject: [PATCH 2/5] add doc --- corelib/src/result.cairo | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index 410b0372019..7a1c5c7d15f 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -201,12 +201,21 @@ //! [`Ok`]: Result::Ok //! [`Err`]: Result::Err //! +//! ## Iterating over `Result` +//! +//! A [`Result`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Result`] is [`Ok`]), or produce no values +//! (when the [`Result`] is [`Err`]). For example, [`into_iter`] +//! contains [`Some(v)`] if the [`Result`] is [`Ok(v)`], and [`None`] if the +//! [`Result`] is [`Err`]. +//! +//! [`into_iter`]: IntoIterator::into_iter #[allow(unused_imports)] use crate::array::{ArrayTrait, SpanTrait}; #[allow(unused_imports)] use crate::serde::Serde; -#[allow(unused_imports)] use crate::iter::{IntoIterator, Iterator}; /// The type used for returning and propagating errors. It is an enum with the variants `Ok: T`, From 898bba6115288ec4ce4f3107db258dfdfcadbfaf Mon Sep 17 00:00:00 2001 From: cairolover <192731503+cairolover@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:22:00 +0100 Subject: [PATCH 3/5] use OptionIter --- corelib/src/option.cairo | 2 +- corelib/src/result.cairo | 30 ++++++------------------------ corelib/src/test/result_test.cairo | 1 + 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/corelib/src/option.cairo b/corelib/src/option.cairo index 3e6c450a45b..34aa9b1d9ea 100644 --- a/corelib/src/option.cairo +++ b/corelib/src/option.cairo @@ -772,7 +772,7 @@ pub impl OptionTraitImpl of OptionTrait { /// [`into_iter`]: IntoIterator::into_iter #[derive(Drop)] pub struct OptionIter { - inner: Option, + pub(crate) inner: Option, } impl OptionIterator of crate::iter::Iterator> { diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index 7a1c5c7d15f..c4f7537244e 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -216,7 +216,6 @@ use crate::array::{ArrayTrait, SpanTrait}; #[allow(unused_imports)] use crate::serde::Serde; -use crate::iter::{IntoIterator, Iterator}; /// The type used for returning and propagating errors. It is an enum with the variants `Ok: T`, /// representing success and containing a value, and `Err: E`, representing error and containing an @@ -698,28 +697,11 @@ pub impl ResultTraitImpl of ResultTrait { } } -/// An iterator over the value in a [`Ok`] variant of a [`Result`]. -/// -/// The iterator yields one value if the result is [`Ok`], otherwise none. -/// -/// This struct is created by the [`into_iter`] method on [`Result`] (provided by the -/// [`IntoIterator`] trait). -/// -/// [`into_iter`]: IntoIterator::into_iter -#[derive(Drop)] -pub struct ResultIter { - inner: Option, -} - -impl ResultIterator> of Iterator> { - type Item = T; - fn next(ref self: ResultIter) -> Option { - self.inner - } -} -impl ResultIntoIterator, +Destruct, +Destruct> of IntoIterator> { - type IntoIter = ResultIter; +impl ResultIntoIterator< + T, E, +Copy, +Destruct, +Destruct, +> of crate::iter::IntoIterator> { + type IntoIter = crate::option::OptionIter; /// Returns a consuming iterator over the possibly contained value. /// @@ -737,7 +719,7 @@ impl ResultIntoIterator, +Destruct, +Destruct> of IntoItera /// assert!(x_iter.next() == Option::None); /// ``` #[inline] - fn into_iter(self: Result) -> ResultIter { - ResultIter { inner: self.ok() } + fn into_iter(self: Result) -> crate::option::OptionIter { + crate::option::OptionIter { inner: self.ok() } } } diff --git a/corelib/src/test/result_test.cairo b/corelib/src/test/result_test.cairo index fee1947b1ed..898ff86c9c4 100644 --- a/corelib/src/test/result_test.cairo +++ b/corelib/src/test/result_test.cairo @@ -319,6 +319,7 @@ fn test_result_ok_iter_next() { let x: Result = Result::Ok(5); let mut x_iter = x.into_iter(); assert!(x_iter.next() == Option::Some(5)); + assert!(x_iter.next() == Option::None); } #[test] From 467a4e6d576b058a17c13a6e65a0a6b8a742a63a Mon Sep 17 00:00:00 2001 From: cairolover <192731503+cairolover@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:39:31 +0100 Subject: [PATCH 4/5] suggestions --- corelib/src/option.cairo | 2 +- corelib/src/result.cairo | 2 +- corelib/src/test/result_test.cairo | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/corelib/src/option.cairo b/corelib/src/option.cairo index 34aa9b1d9ea..3e6c450a45b 100644 --- a/corelib/src/option.cairo +++ b/corelib/src/option.cairo @@ -772,7 +772,7 @@ pub impl OptionTraitImpl of OptionTrait { /// [`into_iter`]: IntoIterator::into_iter #[derive(Drop)] pub struct OptionIter { - pub(crate) inner: Option, + inner: Option, } impl OptionIterator of crate::iter::Iterator> { diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index c4f7537244e..452eb80be90 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -720,6 +720,6 @@ impl ResultIntoIterator< /// ``` #[inline] fn into_iter(self: Result) -> crate::option::OptionIter { - crate::option::OptionIter { inner: self.ok() } + self.ok().into_iter() } } diff --git a/corelib/src/test/result_test.cairo b/corelib/src/test/result_test.cairo index 898ff86c9c4..e77315f60aa 100644 --- a/corelib/src/test/result_test.cairo +++ b/corelib/src/test/result_test.cairo @@ -1,5 +1,4 @@ use crate::result::{Result, ResultTraitImpl}; -use crate::iter::{IntoIterator, Iterator}; #[test] fn test_result_ok_expect() { From fafa451cec084d598c439ee2760af9a60b506478 Mon Sep 17 00:00:00 2001 From: cairolover <192731503+cairolover@users.noreply.github.com> Date: Thu, 2 Jan 2025 20:25:49 +0100 Subject: [PATCH 5/5] remove copy bound --- corelib/src/result.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corelib/src/result.cairo b/corelib/src/result.cairo index 452eb80be90..cc804469eec 100644 --- a/corelib/src/result.cairo +++ b/corelib/src/result.cairo @@ -699,7 +699,7 @@ pub impl ResultTraitImpl of ResultTrait { impl ResultIntoIterator< - T, E, +Copy, +Destruct, +Destruct, + T, E, +Destruct, +Destruct, > of crate::iter::IntoIterator> { type IntoIter = crate::option::OptionIter;