use std::num::NonZeroU32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IterationCount {
kind: IterationCountKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum IterationCountKind {
Count(NonZeroU32),
Infinite,
}
impl IterationCount {
pub const ONCE: Self = Self {
kind: IterationCountKind::Count(NonZeroU32::MIN),
};
pub const INFINITE: Self = Self {
kind: IterationCountKind::Infinite,
};
#[must_use]
pub fn count(count: u32) -> Self {
let count = NonZeroU32::new(count).unwrap_or(NonZeroU32::MIN);
Self {
kind: IterationCountKind::Count(count),
}
}
#[must_use]
pub const fn infinite() -> Self {
Self::INFINITE
}
#[must_use]
pub const fn finite_count(self) -> Option<u32> {
match self.kind {
IterationCountKind::Count(count) => Some(count.get()),
IterationCountKind::Infinite => None,
}
}
}
impl Default for IterationCount {
fn default() -> Self {
Self::ONCE
}
}
impl From<u32> for IterationCount {
fn from(value: u32) -> Self {
Self::count(value)
}
}
#[cfg(test)]
mod tests {
use super::IterationCount;
#[test]
fn count_clamps_zero_to_one() {
assert_eq!(IterationCount::count(0).finite_count(), Some(1));
assert_eq!(IterationCount::count(3).finite_count(), Some(3));
}
#[test]
fn infinite_has_no_finite_count() {
assert_eq!(IterationCount::infinite().finite_count(), None);
}
}