use serde::{Deserialize, Serialize};
use std::num::NonZeroU16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum Item {
Numbers(u32, Option<NonZeroU16>),
Sequence(u32, u16),
}
impl Item {
#[inline]
pub fn new(v: u32) -> Self {
Self::Numbers(v, None)
}
#[inline]
pub fn seq_add(&mut self) {
if let Self::Sequence(_, cnt) = self {
*cnt += 1;
}
}
#[inline]
pub fn len(&self) -> usize {
match self {
Item::Numbers(_, b) => {
if b.is_some() {
2
} else {
1
}
}
Item::Sequence(_, slen) => *slen as usize + 1,
}
}
#[inline]
pub fn at(&self, pos: usize, step_size: u32) -> Option<u32> {
match self {
Item::Numbers(a, b) => match pos {
0 => Some(*a),
1 => Some(a + (*b)?.get() as u32),
_ => None,
},
Item::Sequence(start, cnt) => {
((pos as u16) <= *cnt).then(|| start + (pos as u32 * step_size))
}
}
}
#[inline]
pub fn last_number(&self, step_size: u32) -> u32 {
match self {
Item::Numbers(a, b) => {
if let Some(b) = b {
a + b.get() as u32
} else {
*a
}
}
Item::Sequence(start, count) => start + (step_size * *count as u32),
}
}
#[inline]
pub fn to_sequence(self) -> Self {
match self {
Item::Numbers(a, b) => {
if b.is_some() {
panic!("Can't convert two numbers to sequence");
}
Self::Sequence(a, 0)
}
Item::Sequence(_, _) => self,
}
}
#[inline]
pub fn can_add(&self) -> bool {
match self {
Item::Numbers(_, b) => b.is_none(),
Item::Sequence(_, cnt) => *cnt != u16::MAX,
}
}
#[must_use]
pub(crate) fn is_numbers(&self) -> bool {
matches!(self, Self::Numbers(..))
}
#[must_use]
pub(crate) fn is_sequence(&self) -> bool {
matches!(self, Self::Sequence(..))
}
}