From a12d7d0dfd8327b9b286ef7b2f49ba440a7ef756 Mon Sep 17 00:00:00 2001 From: Julio <30329843+julio4@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:20:34 +0100 Subject: [PATCH] Feat(corelib): `IntoIterator` doc/tests, `iter::traits::collect` module (#6991) --- corelib/src/array.cairo | 4 +- corelib/src/byte_array.cairo | 2 +- corelib/src/iter.cairo | 4 +- corelib/src/iter/traits.cairo | 5 +- corelib/src/iter/traits/collect.cairo | 106 +++++++++++++++++++++++++ corelib/src/iter/traits/iterator.cairo | 25 ------ corelib/src/ops/range.cairo | 2 - corelib/src/option.cairo | 3 +- 8 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 corelib/src/iter/traits/collect.cairo diff --git a/corelib/src/array.cairo b/corelib/src/array.cairo index 4d83548fb8a..fb2da32f6da 100644 --- a/corelib/src/array.cairo +++ b/corelib/src/array.cairo @@ -811,7 +811,7 @@ impl SpanIterator of Iterator> { impl SpanIntoIterator of crate::iter::IntoIterator> { type IntoIter = SpanIter; - fn into_iter(self: Span) -> SpanIter { + fn into_iter(self: Span) -> Self::IntoIter { SpanIter { span: self } } } @@ -840,7 +840,7 @@ impl ArrayIterator of Iterator> { impl ArrayIntoIterator of crate::iter::IntoIterator> { type IntoIter = ArrayIter; - fn into_iter(self: Array) -> ArrayIter { + fn into_iter(self: Array) -> Self::IntoIter { ArrayIter { array: self } } } diff --git a/corelib/src/byte_array.cairo b/corelib/src/byte_array.cairo index 91fbaef4c42..285262c1415 100644 --- a/corelib/src/byte_array.cairo +++ b/corelib/src/byte_array.cairo @@ -509,7 +509,7 @@ impl ByteArrayIterator of crate::iter::Iterator { impl ByteArrayIntoIterator of crate::iter::IntoIterator { type IntoIter = ByteArrayIter; #[inline] - fn into_iter(self: ByteArray) -> ByteArrayIter { + fn into_iter(self: ByteArray) -> Self::IntoIter { ByteArrayIter { current_index: (0..self.len()).into_iter(), ba: self } } } diff --git a/corelib/src/iter.cairo b/corelib/src/iter.cairo index 1bd4484d82b..667b35b4c16 100644 --- a/corelib/src/iter.cairo +++ b/corelib/src/iter.cairo @@ -1,4 +1,2 @@ mod traits; -pub use traits::iterator::IntoIterator; - -pub use traits::iterator::Iterator; +pub use traits::{IntoIterator, Iterator}; diff --git a/corelib/src/iter/traits.cairo b/corelib/src/iter/traits.cairo index d6f79dfadba..9e0ece17783 100644 --- a/corelib/src/iter/traits.cairo +++ b/corelib/src/iter/traits.cairo @@ -1 +1,4 @@ -pub mod iterator; +mod collect; +mod iterator; +pub use collect::IntoIterator; +pub use iterator::Iterator; diff --git a/corelib/src/iter/traits/collect.cairo b/corelib/src/iter/traits/collect.cairo new file mode 100644 index 00000000000..90a02b3962b --- /dev/null +++ b/corelib/src/iter/traits/collect.cairo @@ -0,0 +1,106 @@ +/// Conversion into an [`Iterator`]. +/// +/// By implementing `IntoIterator` for a type, you define how it will be +/// converted to an iterator. This is common for types which describe a +/// collection of some kind. +/// +/// One benefit of implementing `IntoIterator` is that your type will [work +/// with Cairo's `for` loop syntax](crate::iter#for-loops-and-intoiterator). +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let mut iter = array![1, 2, 3].into_iter(); +/// +/// assert_eq!(Option::Some(1), iter.next()); +/// assert_eq!(Option::Some(2), iter.next()); +/// assert_eq!(Option::Some(3), iter.next()); +/// assert_eq!(Option::None, iter.next()); +/// ``` +/// Implementing `IntoIterator` for your type: +/// +/// ``` +/// // A sample collection, that's just a wrapper over Array +/// #[derive(Drop, Debug)] +/// struct MyCollection { +/// arr: Array +/// } +/// +/// // Let's give it some methods so we can create one and add things +/// // to it. +/// #[generate_trait] +/// impl MyCollectionImpl of MyCollectionTrait { +/// fn new() -> MyCollection { +/// MyCollection { +/// arr: ArrayTrait::new() +/// } +/// } +/// +/// fn add(ref self: MyCollection, elem: u32) { +/// self.arr.append(elem); +/// } +/// } +/// +/// // and we'll implement IntoIterator +/// impl MyCollectionIntoIterator of IntoIterator { +/// type IntoIter = crate::array::ArrayIter; +/// fn into_iter(self: MyCollection) -> Self::IntoIter { +/// self.arr.into_iter() +/// } +/// } +/// +/// // Now we can make a new collection... +/// let mut c = MyCollectionTrait::new(); +/// +/// // ... add some stuff to it ... +/// c.add(0); +/// c.add(1); +/// c.add(2); +/// +/// // ... and then turn it into an Iterator: +/// let mut n = 0; +/// for i in c { +/// assert_eq!(i, n); +/// n += 1; +/// }; +/// ``` +pub trait IntoIterator { + /// The iterator type that will be created. + type IntoIter; + impl Iterator: Iterator; + /// Creates an iterator from a value. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: crate::iter + /// + /// # Examples + /// + /// ``` + /// let mut iter = array![1, 2, 3].into_iter(); + /// + /// assert_eq!(Option::Some(1), iter.next()); + /// assert_eq!(Option::Some(2), iter.next()); + /// assert_eq!(Option::Some(3), iter.next()); + /// assert_eq!(Option::None, iter.next()); + /// ``` + fn into_iter(self: T) -> Self::IntoIter; +} + +impl IteratorIntoIterator> of IntoIterator { + type IntoIter = T; + fn into_iter(self: T) -> T { + self + } +} + +impl SnapshotFixedSizeArrayIntoIterator< + T, const SIZE: usize, +Drop, impl ToSpan: core::array::ToSpanTrait<[T; SIZE], T>, +> of IntoIterator<@[T; SIZE]> { + type IntoIter = crate::array::SpanIter; + fn into_iter(self: @[T; SIZE]) -> Self::IntoIter { + ToSpan::span(self).into_iter() + } +} diff --git a/corelib/src/iter/traits/iterator.cairo b/corelib/src/iter/traits/iterator.cairo index 383b70767c5..5b9d580bdee 100644 --- a/corelib/src/iter/traits/iterator.cairo +++ b/corelib/src/iter/traits/iterator.cairo @@ -6,28 +6,3 @@ pub trait Iterator { /// Advance the iterator and return the next value. fn next(ref self: T) -> Option; } - -/// Turn a collection of values into an iterator. -pub trait IntoIterator { - /// The iterator type that will be created. - type IntoIter; - impl Iterator: Iterator; - /// Creates an iterator from a collection. - fn into_iter(self: T) -> Self::IntoIter; -} - -impl IteratorIntoIterator> of IntoIterator { - type IntoIter = T; - fn into_iter(self: T) -> T { - self - } -} - -impl SnapshotFixedSizeArrayIntoIterator< - T, const SIZE: usize, +Drop, impl ToSpan: core::array::ToSpanTrait<[T; SIZE], T>, -> of IntoIterator<@[T; SIZE]> { - type IntoIter = crate::array::SpanIter; - fn into_iter(self: @[T; SIZE]) -> Self::IntoIter { - ToSpan::span(self).into_iter() - } -} diff --git a/corelib/src/ops/range.cairo b/corelib/src/ops/range.cairo index 954943e7290..7fc7d46d5b7 100644 --- a/corelib/src/ops/range.cairo +++ b/corelib/src/ops/range.cairo @@ -127,7 +127,6 @@ impl RangeIntoIterator< -SierraIntRangeSupport, > of IntoIterator> { type IntoIter = RangeIterator; - fn into_iter(self: Range) -> Self::IntoIter { let start = self.start; let end = self.end; @@ -175,7 +174,6 @@ impl SierraRangeIntoIterator< T, +Copy, +Drop, +SierraIntRangeSupport, > of IntoIterator> { type IntoIter = internal::IntRange; - fn into_iter(self: Range) -> Self::IntoIter { match internal::int_range_try_new(self.start, self.end) { Result::Ok(range) => range, diff --git a/corelib/src/option.cairo b/corelib/src/option.cairo index de3464bce8d..8d47cda8a85 100644 --- a/corelib/src/option.cairo +++ b/corelib/src/option.cairo @@ -786,9 +786,8 @@ impl OptionIterator of crate::iter::Iterator> { impl OptionIntoIterator of crate::iter::IntoIterator> { type IntoIter = OptionIter; - #[inline] - fn into_iter(self: Option) -> OptionIter { + fn into_iter(self: Option) -> Self::IntoIter { OptionIter { inner: self } } }