Last active
January 5, 2023 16:38
-
-
Save jirutka/f9ec89f9aa8ac749b92b1a857a630d08 to your computer and use it in GitHub Desktop.
Iterator::array_chunks for stable Rust 1.66
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub(crate) struct ChunksExact<const N: usize, I> { | |
iter: I, | |
} | |
impl<const N: usize, I: Iterator<Item = T>, T> Iterator for ChunksExact<N, I> { | |
type Item = [T; N]; | |
fn next(&mut self) -> Option<Self::Item> { | |
assert_ne!(N, 0); | |
let mut vec: Vec<T> = Vec::with_capacity(N); | |
for _ in 0..N { | |
match self.iter.next() { | |
Some(item) => vec.push(item), | |
None => return None, | |
} | |
} | |
let ary: [T; N] = vec.try_into().unwrap_or_else(|v: Vec<T>| { | |
panic!("Expected a Vec of length {} but it was {}", N, v.len()) | |
}); | |
Some(ary) | |
} | |
} | |
pub(crate) trait ChunksExactIterator: Sized { | |
/// Returns an iterator over `N` elements of the iterator at a time. | |
/// | |
/// This is a custom implementation of [Iterator::array_chunks] for stable | |
/// Rust 1.66, but for simplicity without | |
/// [`.into_remainder()`][std::iter::adapters::ArrayChunks]. | |
/// | |
/// # Panics | |
/// | |
/// Panics if `N` is 0. | |
/// | |
/// # Examples | |
/// | |
/// ``` | |
/// let mut iter = "lorem".chars().array_chunks(); | |
/// assert_eq!(iter.next(), Some(['l', 'o'])); | |
/// assert_eq!(iter.next(), Some(['r', 'e'])); | |
/// assert_eq!(iter.next(), None); | |
/// ``` | |
/// | |
/// TODO: Remove it after `iter_array_chunks` is stabilized. | |
/// https://github.com/rust-lang/rust/issues/100450 | |
fn chunks_exact<const N: usize>(self) -> ChunksExact<N, Self>; | |
} | |
impl<I: Iterator> ChunksExactIterator for I { | |
fn chunks_exact<const N: usize>(self) -> ChunksExact<N, Self> { | |
assert!(N != 0, "chunk size must be non-zero"); | |
ChunksExact { iter: self } | |
} | |
} | |
#[cfg(test)] | |
mod test { | |
use super::*; | |
#[test] | |
fn chunks_exact_with_divisible_input() { | |
let actual = ["a", "b", "c", "d"] | |
.into_iter() | |
.chunks_exact() | |
.collect::<Vec<[&str; 2]>>(); | |
assert_eq!(actual, vec![["a", "b"], ["c", "d"]]); | |
} | |
#[test] | |
fn chunks_exact_with_indivisible_input() { | |
let actual = ["a", "b", "c", "d"] | |
.into_iter() | |
.chunks_exact() | |
.collect::<Vec<[&str; 3]>>(); | |
assert_eq!(actual, vec![["a", "b", "c"]]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment