use core::fmt;
use core::iter::FusedIterator;
use core::num::NonZeroU64;
#[macro_export]
macro_rules! version {
($n:expr) => {
const {
match $crate::Version::new($n) {
::core::option::Option::Some(v) => v,
::core::option::Option::None => {
::core::panic!("version literal must be non-zero")
}
}
}
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version(NonZeroU64);
impl Version {
pub const INITIAL: Self = Self(NonZeroU64::MIN);
#[must_use]
pub const fn next(self) -> Option<Self> {
match self.0.checked_add(1) {
Some(v) => Some(Self(v)),
None => None,
}
}
#[must_use]
pub const fn as_u64(self) -> u64 {
self.0.get()
}
#[must_use]
pub const fn new(v: u64) -> Option<Self> {
match NonZeroU64::new(v) {
Some(nz) => Some(Self(nz)),
None => None,
}
}
#[must_use]
pub fn run(start: Self, len: usize) -> Option<VersionRun> {
let Some(last_index) = len.checked_sub(1) else {
return Some(VersionRun {
next: start,
remaining: 0,
});
};
let last_offset = u64::try_from(last_index).ok()?;
let last_raw = start.as_u64().checked_add(last_offset)?;
Self::new(last_raw)?;
Some(VersionRun {
next: start,
remaining: len,
})
}
}
#[derive(Debug, Clone)]
pub struct VersionRun {
next: Version,
remaining: usize,
}
impl Iterator for VersionRun {
type Item = Version;
fn next(&mut self) -> Option<Version> {
let remaining = self.remaining.checked_sub(1)?;
let current = self.next;
self.remaining = remaining;
if remaining > 0
&& let Some(n) = self.next.next()
{
self.next = n;
}
Some(current)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl ExactSizeIterator for VersionRun {}
impl FusedIterator for VersionRun {}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Debug)]
pub struct VersionedEvent<E> {
version: Version,
event: E,
}
impl<E: Clone> Clone for VersionedEvent<E> {
fn clone(&self) -> Self {
Self {
version: self.version,
event: self.event.clone(),
}
}
}
impl<E: PartialEq> PartialEq for VersionedEvent<E> {
fn eq(&self, other: &Self) -> bool {
self.version == other.version && self.event == other.event
}
}
impl<E: Eq> Eq for VersionedEvent<E> {}
impl<E> VersionedEvent<E> {
#[must_use]
pub const fn version(&self) -> Version {
self.version
}
#[must_use]
pub const fn event(&self) -> &E {
&self.event
}
#[must_use]
pub fn into_parts(self) -> (Version, E) {
(self.version, self.event)
}
#[must_use]
pub const fn new(version: Version, event: E) -> Self {
Self { version, event }
}
}