///|
pub fn TimeTag::immediate() -> TimeTag {
{ seconds: 0U, fraction: 1U, }
}
///|
pub fn TimeTag::is_immediate(self : TimeTag) -> Bool {
self.seconds == 0U && self.fraction == 1U
}
///|
pub fn TimeTag::bits(self : TimeTag) -> UInt64 {
(self.seconds.to_uint64() << 32) | self.fraction.to_uint64()
}
///|
pub fn TimeTag::from_bits(bits : UInt64) -> TimeTag {
{ seconds: (bits >> 32).to_uint(), fraction: bits.to_uint(), }
}
///|
/// Era 0 only, floors nanoseconds to the preceding 2^-32-second tick.
pub fn TimeTag::from_unix(
seconds : Int64,
nanoseconds~ : Int32 = 0,
) -> TimeTag raise OscError {
if seconds < -2208988800L || seconds > 2085978495L {
raise Invalid("Unix seconds outside NTP era 0", 0)
}
if nanoseconds < 0 || nanoseconds >= 1000000000 {
raise Invalid("nanoseconds must be 0..999999999", 0)
}
let t = TimeTag::{
seconds: (seconds + 2208988800L).reinterpret_as_uint64().to_uint(),
fraction: ((nanoseconds.to_uint64() << 32) / 1000000000UL).to_uint(),
}
if t.is_immediate() {
raise Invalid("timestamp collides with OSC immediate sentinel", 0)
}
t
}
///|
pub fn TimeTag::to_unix(self : TimeTag) -> (Int64, Int32) raise OscError {
if self.is_immediate() {
raise Invalid("immediate is not an absolute timestamp", 0)
}
(
self.seconds.to_int64() - 2208988800L,
((self.fraction.to_uint64() * 1000000000UL) >> 32).to_int(),
)
}
///|
pub fn TimeTag::resolve(
self : TimeTag,
now : TimeTag,
) -> TimeTag raise OscError {
if now.is_immediate() {
raise Invalid("now must be an absolute era-0 timetag", 0)
}
if self.is_immediate() {
now
} else {
self
}
}
///|
pub fn TimeTag::add_ticks(
self : TimeTag,
ticks : UInt64,
) -> TimeTag raise OscError {
if self.is_immediate() {
raise Invalid("cannot add to immediate", 0)
}
let bits = self.bits()
if ticks > 0xffffffffffffffffUL - bits {
raise Invalid("NTP era overflow", 0)
}
let out = TimeTag::from_bits(bits + ticks)
if out.is_immediate() {
raise Invalid("timestamp collides with immediate sentinel", 0)
}
out
}
///|
pub fn TimeTag::distance_ticks(
self : TimeTag,
later : TimeTag,
) -> UInt64 raise OscError {
if self.is_immediate() || later.is_immediate() || later.bits() < self.bits() {
raise Invalid("ordered absolute timetags required", 0)
}
later.bits() - self.bits()
}