Crate serial_num

source ·
Expand description

Serial number type with wraparound.

Simple example

use serial_num::Serial;

// the default is a reference point - not serial number "zero"
let mut a = Serial::default();
let mut b = Serial::default();
let mut c = Serial::default();

// three ways to increase
let x = a.increase_get(); // increase, then copy
let y = b.get_increase(); // copy, then increase
c.increase();

assert!(y < x);
assert_eq!(-1_i16, y.diff(x)); // "diff()" is signed
assert_eq!(1_u16, y.dist(x)); // "dist()" is unsigned

// addition is the same as calling "increase()" n times
assert_eq!(y + 1_u16, x);

Wraparound example

use serial_num::Serial;

// a serial number can be increased indefinitely
let mut x = Serial::default();
for _ in 0..u16::MAX {
    x.increase();
}
let x = x + u16::MAX + u16::MAX + u16::MAX;

// comparison is trivial as long as two serial numbers have
// a distance of less than half of our number space (32767).
let a = Serial::default() + 5;
let b = Serial::default() + 32000;
assert!(a < b); // 5th successor < 32000th successor

// but: the comparison flips if the distance is larger
let a = Serial::default() + 5;
let b = Serial::default() + 65000;
assert!(a > b); // 5th successor > 65000th successor

// this means that you get the right ordering as long as
// you compare one serial number at most with one that
// is its 32767th successor.

// a real use case of this is to sign UDP packets with
// a serial number. this would allow you to restore the
// order of packets at the receiver as long as you never
// look at more than the 32767 last packets (which
// should be much more than you need).

The NAN value

use serial_num::Serial;

// "NAN" exists to have value representing "no serial number",
// since it saves encoding space vs wrapping Serial in an Option.
let nan = Serial::NAN;
let default = Serial::default();

// you can check whether a serial number is NAN
assert!(nan.is_nan());

// NAN cannot be increased
assert_eq!(Serial::NAN, nan + 1_u16);

// distance between two NAN values is zero
assert_eq!(0_u16, nan.dist(nan));
assert_eq!(0_i16, nan.diff(nan));

// distance and difference of non-NAN to NAN is the maximum distance
assert_eq!(32_767_u16, default.dist(nan));
assert_eq!(32_767_u16, nan.dist(default));
assert_eq!(32_767_i16, default.diff(nan));
assert_eq!(32_767_i16, nan.diff(default));

// partial ordering does not include the NAN value
assert_eq!(None, nan.partial_cmp(&default));
assert!(!(nan < default) && !(nan >= default));

Structs

  • Two-byte serial number with wraparound.