Skip to content

Commit

Permalink
feat(corelib): Iterator::enumerate (#7048)
Browse files Browse the repository at this point in the history
  • Loading branch information
julio4 authored Jan 15, 2025
1 parent 07cf582 commit 0ec6865
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
5 changes: 5 additions & 0 deletions corelib/src/iter/adapters.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ mod map;
pub use map::Map;
#[allow(unused_imports)]
pub(crate) use map::mapped_iterator;

mod enumerate;
pub use enumerate::Enumerate;
#[allow(unused_imports)]
pub(crate) use enumerate::enumerated_iterator;
41 changes: 41 additions & 0 deletions corelib/src/iter/adapters/enumerate.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// An iterator that yields the current count and the element during iteration.
///
/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`enumerate`]: Iterator::enumerate
/// [`Iterator`]: core::iter::Iterator
#[must_use]
#[derive(Drop, Clone, Debug)]
pub struct Enumerate<I> {
iter: I,
count: usize,
}

pub fn enumerated_iterator<I>(iter: I) -> Enumerate<I> {
Enumerate { iter, count: 0 }
}

impl EnumerateIterator<
I, T, +Iterator<I>[Item: T], +Destruct<I>, +Destruct<T>,
> of Iterator<Enumerate<I>> {
type Item = (usize, T);

/// # Overflow Behavior
///
/// The method does no guarding against overflows, so enumerating more than
/// `Bounded::<usize>::MAX` elements will always panic.
///
/// [`Bounded`]: core::num::traits::Bounded
///
/// # Panics
///
/// Will panic if the index of the element overflows a `usize`.
#[inline]
fn next(ref self: Enumerate<I>) -> Option<Self::Item> {
let a = self.iter.next()?;
let i = self.count;
self.count += 1;
Option::Some((i, a))
}
}
37 changes: 36 additions & 1 deletion corelib/src/iter/traits/iterator.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::iter::adapters::{Map, mapped_iterator};
use crate::iter::adapters::{Enumerate, Map, enumerated_iterator, mapped_iterator};

/// A trait for dealing with iterators.
///
Expand Down Expand Up @@ -93,4 +93,39 @@ pub trait Iterator<T> {
) -> Map<T, F> {
mapped_iterator(self, f)
}

/// Creates an iterator which gives the current iteration count as well as
/// the next value.
///
/// The iterator returned yields pairs `(i, val)`, where `i` is the
/// current index of iteration and `val` is the value returned by the
/// iterator.
///
/// `enumerate()` keeps its count as a [`usize`].
///
/// # Overflow Behavior
///
/// The method does no guarding against overflows, so enumerating more than
/// `Bounded::<usize>::MAX` elements will always panic.
///
/// [`Bounded`]: core::num::traits::Bounded
///
/// # Panics
///
/// Will panic if the to-be-returned index overflows a `usize`.
///
/// # Examples
///
/// ```
/// let mut iter = array!['a', 'b', 'c'].into_iter().enumerate();
///
/// assert_eq!(iter.next(), Option::Some((0, 'a')));
/// assert_eq!(iter.next(), Option::Some((1, 'b')));
/// assert_eq!(iter.next(), Option::Some((2, 'c')));
/// assert_eq!(iter.next(), Option::None);
/// ```
#[inline]
fn enumerate(self: T) -> Enumerate<T> {
enumerated_iterator(self)
}
}
9 changes: 9 additions & 0 deletions corelib/src/test/iter_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ fn test_iter_adapter_map() {
assert_eq!(iter.next(), Option::Some(6));
assert_eq!(iter.next(), Option::None);
}

fn test_iterator_enumerate() {
let mut iter = array!['a', 'b', 'c'].into_iter().enumerate();

assert_eq!(iter.next(), Option::Some((0, 'a')));
assert_eq!(iter.next(), Option::Some((1, 'b')));
assert_eq!(iter.next(), Option::Some((2, 'c')));
assert_eq!(iter.next(), Option::None);
}

0 comments on commit 0ec6865

Please sign in to comment.