# serial-uint
Generic serial number arithmetic following [RFC 1982](https://datatracker.ietf.org/doc/html/rfc1982) semantics.
A serial number is a fixed-width unsigned integer whose operations *wrap around*. Its defining
difference from an ordinary integer is **comparison**: in the wraparound space `MAX` is the
predecessor of `0`, so `Serial(MAX) < Serial(0)`.
- `no_std` — depends only on `core`.
- Generic over `u8` / `u16` / `u32` / `u64` / `u128` / `usize`.
- Wraparound add / subtract with an offset.
- RFC 1982 wraparound comparison via `PartialOrd`. When two values are exactly half a cycle apart
their ordering is undefined and `partial_cmp` returns `None` (this is why `PartialOrd` is used
instead of `Ord`).
- Compare and test equality directly against the raw underlying value, in both directions.
## Usage
```rust
use serial_uint::Serial;
let a = Serial::<u8>::new(250);
let b = a + 10; // wraparound: 250 + 10 = 4
assert_eq!(b.value(), 4);
// wraparound comparison: a precedes b
assert!(a < b);
// MAX is the predecessor of 0
assert!(Serial::<u8>::new(u8::MAX) < Serial::<u8>::new(0));
// compare directly against a raw value (also wraparound)
assert!(a < 4u8);
assert!(4u8 > a);
// exactly half a cycle apart -> undefined ordering
assert_eq!(Serial::<u8>::new(0).partial_cmp(&128u8), None);
```
## Semantics
For two serial numbers, let `d = (other - self) mod 2^BITS`:
| `0` | equal |
| `0 < d < HALF` | `self < other`|
| `d == HALF` | undefined (`None`) |
| `d > HALF` | `self > other`|
where `HALF = 2^(BITS-1)`. Per RFC 1982 the largest valid addend is `HALF - 1`; larger addends are
undefined and trigger a `debug_assert!` in debug builds.
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT license ([LICENSE-MIT](LICENSE-MIT))
at your option.