use core::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Revision(u64);
impl Revision {
pub(crate) const START: Revision = Revision(0);
pub(crate) fn next(self) -> Revision {
Revision(self.0.saturating_add(1))
}
#[must_use]
#[inline]
pub const fn as_u64(self) -> u64 {
self.0
}
}
impl fmt::Display for Revision {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "r{}", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_start_is_zero() {
assert_eq!(Revision::START.as_u64(), 0);
}
#[test]
fn test_next_advances_by_one() {
assert_eq!(Revision::START.next().as_u64(), 1);
assert_eq!(Revision::START.next().next().as_u64(), 2);
}
#[test]
fn test_ordering_reflects_age() {
assert!(Revision::START.next() > Revision::START);
assert!(Revision::START < Revision::START.next());
}
#[test]
fn test_next_saturates_at_max() {
let max = Revision(u64::MAX);
assert_eq!(max.next(), max);
}
#[test]
fn test_display_is_prefixed() {
use alloc::string::ToString;
assert_eq!(Revision(7).to_string(), "r7");
}
}