Skip to content
Advanced

Indices and sequence numbers

A Fixed<Sample, One, u32> is an amount: 50 samples. A position is something else: sample number 100 of a capture, channel 3 of 4, frame 250. With the feature counting:

Type What Refused
Index<Of, T, B> a 0-based position in a table of Of outside B
IndexFrom1<Of, T, B> a 1-based position, as people count 0, outside B
Seq<Of, T> a wrapping sequence number nothing: every T is one

Index

The algebra is a point's: the table's start is the origin.

use exact_units::{Fixed, Index, units::Sample};

let start = Index::<Sample, u32>::new(100);
let end = start + Fixed::new(50);
assert_eq!(end.get(), 150);
assert_eq!(end - start, Fixed::new(50)); // two positions are apart by an amount

Two positions don't add:

use exact_units::{Index, units::Sample};

let _ = Index::<Sample, u32>::new(1) + Index::<Sample, u32>::new(2);

A table of 8 is Range<0, 7>, checked on construction and on every read from the wire:

use exact_units::{Fixed, Index, Range, units::Item};

type Slot = Index<Item, u8, Range<0, 7>>;

let last = Slot::try_new(7).unwrap();
assert!(Slot::try_new(8).is_err());
assert_eq!(last.checked_add(Fixed::new(1)), None);

IndexFrom1

Channel 1 to 4, motor 1 to 4: never 0. to_index gives the 0-based position.

use exact_units::{Index, IndexFrom1, Range, units::Item};

type Channel = IndexFrom1<Item, u8, Range<1, 4>>;

let ch = Channel::try_new(3).unwrap();
assert_eq!(ch.to_index(), Index::new(2));
assert!(Channel::try_new(0).is_err());

Seq

A frame's or a request's number moves on modulo \(2^{\text{bits}}\) and compares in serial number order (RFC 1982): \(a\) is before \(b\) when

\[ 0 < (b - a) \bmod 2^{n} < 2^{n-1} \]
0 64 128 192 250 4 Seq: 256 numbers on a ring 250, then 10 more: 4 4 is after 250: 10 steps ahead, less than half the ring the green half is after 250 the rest is before it
Integer order is wrong across the wrap: 4 < 250, yet frame 4 came after frame 250.
use exact_units::{Seq, units::Frame};

let a = Seq::<Frame, u8>::new(250);
let b = a.wrapping_add(10);
assert_eq!(b.get(), 4);
assert!(a.is_before(b));
// 10 frames forward, a Fixed<Frame, One, u8, Wrapping>
assert_eq!(a.distance(b).get(), 10);

A Seq has no <: serial order isn't transitive, and two numbers exactly half the ring apart have no order at all (serial_cmp returns None).