diff --git a/README.md b/README.md index 6fac41f..f59034d 100644 --- a/README.md +++ b/README.md @@ -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>` elements. +for peekable iterators, slices and other common collections. But nothing stops you to implement this trait for other collections as well! @@ -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::>() .try_into() .unwrap(); @@ -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 | diff --git a/src/iter.rs b/src/iter.rs new file mode 100644 index 0000000..10f8355 --- /dev/null +++ b/src/iter.rs @@ -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 { + /// Pass key to the peeked item. + Peek(Key), + /// Pass key to the `n`th item. + Nth(Key, usize), +} + +impl PeekableKey { + /// 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 Default for PeekableKey +where + Key: Default, +{ + fn default() -> Self { + let key = Default::default(); + Self::Peek(key) + } +} + +impl<'a, I, Item, Key> Many<'a, PeekableKey> for Peekable +where + I: Iterator, + Item: Many<'a, Key>, +{ + type Ref = Option; + + fn try_move_ref(&mut self, key: PeekableKey) -> Result { + let (key, item) = peek_by_key(self, key); + item.map(|item| item.try_move_ref(key)).transpose() + } + + type Mut = Option; + + fn try_move_mut(&mut self, key: PeekableKey) -> Result { + let (key, item) = peek_by_key(self, key); + item.map(|item| item.try_move_mut(key)).transpose() + } +} + +fn peek_by_key(iter: &mut Peekable, key: PeekableKey) -> (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()) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 7643804..a7a8d0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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>` elements. +//! for peekable iterators, [slices] and other common collections. //! //! But nothing stops you to implement this trait for other collections as well! //! @@ -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::>() //! .try_into() //! .unwrap(); @@ -99,6 +99,8 @@ pub use self::{ many::{Many, MoveError, Result}, }; +pub mod iter; + #[cfg(feature = "alloc")] mod alloc; #[cfg(feature = "hashbrown")]