// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// A time budget measured from the instant it started.
///
/// A budget of zero or less never expires, which is how most servers spell "no
/// timeout": a configuration that leaves the timeout unset should not time
/// everything out at once.
pub struct Deadline {
start : Int64
budget : Int64
}
///|
/// A deadline of `budget` starting at `now`.
///
/// # Parameters
/// - `budget` : how long the deadline lasts; zero or less never expires
/// - `now` : the clock reading it starts at
pub fn Deadline::start(budget : @moondate.Span, now : Int64) -> Deadline {
{ start: now, budget: budget.nanos, }
}
///|
/// Whether the budget is spent at `now`.
///
/// # Parameters
/// - `now` : the caller's clock reading, in nanoseconds
pub fn Deadline::expired(self : Deadline, now : Int64) -> Bool {
self.budget > 0L && now - self.start >= self.budget
}
///|
/// What is left of the budget at `now`, never negative. `None` when there is no
/// budget, which has no finite remainder.
///
/// # Parameters
/// - `now` : the caller's clock reading, in nanoseconds
pub fn Deadline::remaining(self : Deadline, now : Int64) -> @moondate.Span? {
guard self.budget > 0L else { None }
let left = self.budget - (now - self.start)
Some({ nanos: if left < 0L { 0L } else { left }, })
}