use core::fmt;
use std::iter::FusedIterator;
use crate::error::{Error, Result};
#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct SimpleRange {
pub start: u32,
pub end: u32,
current: Option<u32>,
}
impl fmt::Display for SimpleRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.start == self.end {
write!(f, "{}", self.start)
} else {
write!(f, "{}-{}", self.start, self.end)
}
}
}
impl SimpleRange {
pub const fn new(start: u32, end: u32) -> Result<Self> {
if start > end {
return Err(Error::InvalidRangeReversed { start, end });
}
if end == u32::MAX {
return Err(Error::TooLarge(end));
}
Ok(Self {
start,
end,
current: Some(start),
})
}
pub fn reset(&mut self) {
self.current = Some(self.start);
}
pub const fn len(&self) -> usize {
if let Some(current) = self.current {
(self.end - current + 1) as usize
} else {
0
}
}
pub const fn iter(&self) -> SimpleRangeIter {
SimpleRangeIter {
current: self.start,
end: self.end,
}
}
}
impl Iterator for SimpleRange {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if let Some(current) = self.current {
self.current = if current == self.end {
None
} else {
Some(current + 1)
};
Some(current)
} else {
None
}
}
}
impl IntoIterator for &SimpleRange {
type Item = u32;
type IntoIter = SimpleRangeIter;
fn into_iter(self) -> Self::IntoIter {
SimpleRangeIter {
current: self.start,
end: self.end,
}
}
}
#[derive(Debug)]
pub struct SimpleRangeIter {
current: u32,
end: u32,
}
impl Iterator for SimpleRangeIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.current <= self.end {
let result = self.current;
self.current += 1; Some(result)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = if self.current <= self.end {
(self.end - self.current + 1) as usize
} else {
0
};
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for SimpleRangeIter {
fn len(&self) -> usize {
if self.current <= self.end {
(self.end - self.current + 1) as usize
} else {
0
}
}
}
impl FusedIterator for SimpleRangeIter {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simplerange_len() {
let range = SimpleRange::new(1, 1_000_000_000).unwrap();
assert_eq!(range.len(), 1_000_000_000);
}
#[test]
fn test_simplerange_len_limits() -> Result<()> {
let toolarge = SimpleRange::new(0, u32::MAX);
assert!(matches!(toolarge, Err(Error::TooLarge(_))));
let range = SimpleRange::new(0, u32::MAX - 1)?;
assert_eq!(range.len(), u32::MAX as usize);
Ok(())
}
#[test]
fn test_simplerange_iterator() {
let mut expected = vec![1, 2, 3, 4, 5];
let simplerange = SimpleRange::new(1, 5).unwrap();
for elem in simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
let mut simplerange = SimpleRange::new(1, 5).unwrap();
assert_eq!(simplerange.next(), Some(1));
assert_eq!(simplerange.next(), Some(2));
assert_eq!(simplerange.next(), Some(3));
assert_eq!(simplerange.next(), Some(4));
assert_eq!(simplerange.next(), Some(5));
assert_eq!(simplerange.next(), None);
assert_eq!(simplerange.len(), 0);
simplerange.reset();
assert_eq!(simplerange.len(), 5);
assert_eq!(simplerange.next(), Some(1));
assert_eq!(simplerange.len(), 4);
}
#[test]
fn test_simplerange_iter() {
let expected_orig = vec![1, 2, 3, 4, 5];
let simplerange = SimpleRange::new(1, 5).unwrap();
let mut expected = expected_orig.clone();
for elem in &simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
assert!(expected.is_empty());
let mut expected = expected_orig.clone();
for elem in &simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
assert!(expected.is_empty());
let expected = expected_orig;
let elems: Vec<u32> = simplerange.iter().collect();
assert_eq!(expected, elems);
}
#[test]
fn test_simplerange_intoiter() {
let expected_orig = vec![1, 2, 3, 4, 5];
let simplerange = SimpleRange::new(1, 5).unwrap();
let mut expected = expected_orig.clone();
for elem in &simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
assert!(expected.is_empty());
let mut expected = expected_orig.clone();
for elem in &simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
assert!(expected.is_empty());
let mut expected = expected_orig;
for elem in simplerange {
let e = expected.remove(0);
assert_eq!(e, elem);
}
assert!(expected.is_empty());
}
#[test]
fn test_simplerange_exactsizeiterator() {
fn inner(_: impl ExactSizeIterator) {
}
let simplerange = SimpleRange::new(1, 1).unwrap();
inner(simplerange.iter());
}
}