use std::cmp::Ordering;
use std::fmt;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Serial {
increment: u32,
alternate: bool,
}
impl Serial {
pub fn zero() -> Self {
Serial {
increment: 0,
alternate: false,
}
}
pub fn next(&self) -> Serial {
let mut serial = self.clone();
let (new, overflowed) = serial.increment.overflowing_add(1);
serial.increment = new;
if overflowed {
serial.alternate = !serial.alternate;
}
serial
}
pub fn incr(&mut self) -> Serial {
let next = self.next();
*self = next;
*self
}
}
impl fmt::Debug for Serial {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Serial")
}
}
impl Ord for Serial {
fn cmp(&self, other: &Serial) -> Ordering {
let cmp = self.increment.cmp(&other.increment);
if self.alternate != other.alternate {
cmp.reverse()
} else {
cmp
}
}
}
impl PartialOrd for Serial {
fn partial_cmp(&self, other: &Serial) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[cfg(test)]
mod tests {
use super::Serial;
#[test]
fn test_basic_ordering() {
let old = Serial::zero();
let new = old.next();
assert!(old < new);
}
#[test]
fn test_overflowing() {
let mut old1 = Serial::zero();
old1.increment = ::std::u32::MAX - 1;
let old2 = old1.next();
let old3 = old2.next();
let new = old3.next();
assert_eq!(old1.increment, ::std::u32::MAX - 1);
assert_eq!(old2.increment, ::std::u32::MAX);
assert_eq!(old3.increment, 0);
assert_eq!(new.increment, 1);
assert!(old1 < old2);
assert!(old2 < old3);
assert!(old3 < new);
assert!(old1 < new);
}
#[test]
fn test_incr() {
let mut serial = Serial::zero();
let original = serial.clone();
serial.incr();
assert!(serial > original);
}
}