Skip to content

Commit

Permalink
Implement Many trait for peekable iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
tuguzT committed Jun 24, 2023
1 parent 7a2b14d commit 3f4a440
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 5 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ But the most importantly, this crate allows to retrieve **many** mutable referen
out of the collection by creating a new collection which holds these references.

For that very case, crate defines `Many` trait which is implemented
for slices of `Option<RefKind<'a, T>>` elements.
for peekable iterators, slices and other common collections.

But nothing stops you to implement this trait for other collections as well!

Expand All @@ -28,7 +28,7 @@ let mut array: [_; 10] = array::from_fn(|i| i * i);
// Create collection of mutable references on all of the array elements
let mut many: [_; 10] = array
.iter_mut()
.map(|sq| Some(RefKind::Mut(sq)))
.map(|sq| Some(RefKind::from(sq)))
.collect::<Vec<_>>()
.try_into()
.unwrap();
Expand Down Expand Up @@ -75,7 +75,7 @@ This crate contains no `unsafe` code.
This crate has the following Cargo features:

| Feature name | Description |
|--------------|---------------------------------------------------------------------------------------|
| ------------ | ------------------------------------------------------------------------------------- |
| `alloc` | Implements `Many` trait for `VecDeque` and `BTreeMap` in `alloc` crate |
| `std` | Implements `Many` trait for `HashMap` in standard library, depends on `alloc` feature |
| `hashbrown` | Implements `Many` trait for `HashMap` in `hashbrown` crate |
Expand Down
83 changes: 83 additions & 0 deletions src/iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! Provides peekable key for [`Peekable`] iterator
//! and implementation of [`Many`] trait for this type of iterator.
use core::iter::Peekable;

use crate::many::{Many, Result};

/// Type of key for peekable iterator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PeekableKey<Key> {
/// Pass key to the peeked item.
Peek(Key),
/// Pass key to the `n`th item.
Nth(Key, usize),
}

impl<Key> PeekableKey<Key> {
/// Creates new peekable key that passes provided key to the peeked element.
pub fn peek(key: Key) -> Self {
Self::Peek(key)
}

/// Creates new peekable key that passes provided key to the next element.
pub fn next(key: Key) -> Self {
Self::Nth(key, 0)
}

/// Creates new peekable key that passes provided key to the `n`th element.
pub fn nth(key: Key, n: usize) -> Self {
Self::Nth(key, n)
}

/// Turns this peekable key into the inner key.
pub fn into_key(self) -> Key {
match self {
Self::Peek(key) => key,
Self::Nth(key, _) => key,
}
}
}

impl<Key> Default for PeekableKey<Key>
where
Key: Default,
{
fn default() -> Self {
let key = Default::default();
Self::Peek(key)
}
}

impl<'a, I, Item, Key> Many<'a, PeekableKey<Key>> for Peekable<I>
where
I: Iterator<Item = Item>,
Item: Many<'a, Key>,
{
type Ref = Option<Item::Ref>;

fn try_move_ref(&mut self, key: PeekableKey<Key>) -> Result<Self::Ref> {
let (key, item) = peek_by_key(self, key);
item.map(|item| item.try_move_ref(key)).transpose()
}

type Mut = Option<Item::Mut>;

fn try_move_mut(&mut self, key: PeekableKey<Key>) -> Result<Self::Mut> {
let (key, item) = peek_by_key(self, key);
item.map(|item| item.try_move_mut(key)).transpose()
}
}

fn peek_by_key<I, Key>(iter: &mut Peekable<I>, key: PeekableKey<Key>) -> (Key, Option<&mut I::Item>)
where
I: Iterator,
{
match key {
PeekableKey::Peek(key) => (key, iter.peek_mut()),
PeekableKey::Nth(key, n) => {
let _ = iter.nth(n);
(key, iter.peek_mut())
}
}
}
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//! out of the collection by creating a new collection which holds these references.
//!
//! For that very case, crate defines [`Many`] trait which is implemented
//! for [slices] of `Option<RefKind<'a, T>>` elements.
//! for peekable iterators, [slices] and other common collections.
//!
//! But nothing stops you to implement this trait for other collections as well!
//!
Expand All @@ -29,7 +29,7 @@
//! // Create collection of mutable references on all of the array elements
//! let mut many: [_; 10] = array
//! .iter_mut()
//! .map(|sq| Some(RefKind::Mut(sq)))
//! .map(|sq| Some(RefKind::from(sq)))
//! .collect::<Vec<_>>()
//! .try_into()
//! .unwrap();
Expand Down Expand Up @@ -99,6 +99,8 @@ pub use self::{
many::{Many, MoveError, Result},
};

pub mod iter;

#[cfg(feature = "alloc")]
mod alloc;
#[cfg(feature = "hashbrown")]
Expand Down

0 comments on commit 3f4a440

Please sign in to comment.