pub struct Timestamp { /* private fields */ }Expand description
A timestamp in a track’s timescale (units per second).
All timestamps within a track are relative, so zero for one track is not zero for another.
The underlying value is constrained to fit within a QUIC VarInt (2^62 - 1) so it can be
encoded and decoded easily; the scale is carried alongside so frames from different
sources can be compared and converted without lossy detours through a single fixed scale.
The scale is a Timescale (always non-zero), so unit conversions (as_secs, as_millis,
etc.) are infallible. Use Option<Timestamp> at call sites that need a “missing” sentinel
instead of relying on a magic value.
§An instant, not a number
A Timestamp is a point in time (like std::time::Instant), not a scalar, so it has no
arithmetic operators: adding two instants is meaningless, and a scale mismatch can’t be a
silent panic. Use Self::checked_add / Self::checked_sub, which require both
operands to share a scale and return TimeOverflow otherwise. To combine timestamps
from different scales, Self::convert one to the other’s scale first.
§Equality vs ordering
These two intentionally disagree, so pick the one you mean:
Eq/Hashare structural (field-wise):from_secs(1) != from_millis(1000), because they encode as different(value, scale)pairs on the wire. Two timestamps are equal only when both their value and scale match.Ordis temporal: it cross-multiplies scales, sofrom_millis(1000)orders afterfrom_millis(999)andfrom_secs(1)slots in between. When a cross-scale comparison is otherwise a tie, it breaks by(scale, value)to stay consistent withEq.
So from_secs(1).cmp(&from_millis(1000)) is not Equal, and neither is == true. If you
want “same instant regardless of encoding”, compare after a Self::convert to a common scale.
Implementations§
Source§impl Timestamp
impl Timestamp
Sourcepub const ZERO: Self
pub const ZERO: Self
The zero timestamp: value 0 at Timescale::SECOND.
The scale is not incidental. Equality and ordering are scale-aware (see the type
docs), so this is not interchangeable with 0 at another scale; use
Self::is_zero to test a zero value regardless of scale. In particular, don’t
seed a .max() accumulator with this: a later value at a finer scale would lose
the tie-break. Reach for Option<Timestamp> instead.
Sourcepub const fn new(value: u64, scale: Timescale) -> Result<Self, TimeOverflow>
pub const fn new(value: u64, scale: Timescale) -> Result<Self, TimeOverflow>
Construct a timestamp directly from a raw value at the given scale.
Returns TimeOverflow if value exceeds 2^62 - 1.
Sourcepub fn from_scale(
value: u64,
units_per_second: u64,
) -> Result<Self, TimeOverflow>
pub fn from_scale( value: u64, units_per_second: u64, ) -> Result<Self, TimeOverflow>
Construct a timestamp from a raw value and a units_per_second scale.
Returns TimeOverflow if the scale is zero or the value is out of range.
Sourcepub const fn from_secs(seconds: u64) -> Result<Self, TimeOverflow>
pub const fn from_secs(seconds: u64) -> Result<Self, TimeOverflow>
Convert a number of seconds to a timestamp at Timescale::SECOND.
Sourcepub const fn from_millis(millis: u64) -> Result<Self, TimeOverflow>
pub const fn from_millis(millis: u64) -> Result<Self, TimeOverflow>
Convert a number of milliseconds to a timestamp at Timescale::MILLI.
Sourcepub const fn from_micros(micros: u64) -> Result<Self, TimeOverflow>
pub const fn from_micros(micros: u64) -> Result<Self, TimeOverflow>
Convert a number of microseconds to a timestamp at Timescale::MICRO.
Sourcepub const fn from_nanos(nanos: u64) -> Result<Self, TimeOverflow>
pub const fn from_nanos(nanos: u64) -> Result<Self, TimeOverflow>
Convert a number of nanoseconds to a timestamp at Timescale::NANO.
Sourcepub const fn convert(self, new_scale: Timescale) -> Result<Self, TimeOverflow>
pub const fn convert(self, new_scale: Timescale) -> Result<Self, TimeOverflow>
Re-express this timestamp at a new scale. Returns TimeOverflow if the new
value would exceed 2^62 - 1.
Sourcepub const fn as_scale(self, target: Timescale) -> u128
pub const fn as_scale(self, target: Timescale) -> u128
The value re-expressed at target as a u128.
Sourcepub const fn checked_add(self, rhs: Self) -> Result<Self, TimeOverflow>
pub const fn checked_add(self, rhs: Self) -> Result<Self, TimeOverflow>
Add two timestamps. Returns TimeOverflow if the sum exceeds 2^62 - 1 or
if the scales differ.
Sourcepub const fn checked_sub(self, rhs: Self) -> Result<Self, TimeOverflow>
pub const fn checked_sub(self, rhs: Self) -> Result<Self, TimeOverflow>
Subtract rhs from self. Returns TimeOverflow if rhs > self or if the
scales differ.
Sourcepub fn now() -> Self
pub fn now() -> Self
Current point on the local monotonic clock, expressed in the default timescale
(Timescale::MILLI).
This is the one-way bridge from a local clock to a track timestamp: there is
deliberately no inverse (a Timestamp is relative and jittered, never a clock).
Used to stamp frames that arrive without one, e.g. on protocols whose wire can’t
carry a timestamp. Uses web_async::time::Instant::now so it works on wasm and honors
tokio::time::pause in tests.
Trait Implementations§
impl Copy for Timestamp
impl Eq for Timestamp
Source§impl From<Instant> for Timestamp
impl From<Instant> for Timestamp
Source§fn from(instant: Instant) -> Self
fn from(instant: Instant) -> Self
Convert an std::time::Instant into a millisecond-scale timestamp (the default
timescale), anchored at 2020-01-01 plus a per-process jitter (see TIME_ANCHOR).
One-way only: there is no inverse, since the anchor is jittered to keep a
Timestamp from being read back as a clock.
Source§impl Ord for Timestamp
impl Ord for Timestamp
Source§fn cmp(&self, other: &Self) -> Ordering
fn cmp(&self, other: &Self) -> Ordering
Temporal comparison, normalizing across scales (see the type-level docs for how
this relates to structural Eq).
- Equal scales compare raw values directly.
- Otherwise cross-multiplies in 128-bit so e.g.
1s > 2msorders correctly. - A would-be cross-scale tie (e.g.
from_secs(1)vsfrom_millis(1000)) breaks by(scale, value), keepingOrdconsistent with the field-wiseEq/Hash.