use super::{Accuracy, BoundUncertainty, earliest, latest};
use structured_pkix::temporal::{Instant, LeapTable, Reading};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RequestWindow {
start: Instant,
end: Instant,
}
impl RequestWindow {
#[must_use]
pub fn for_unique_imprint(start: Instant, end: Instant) -> Option<Self> {
if start > end {
return None;
}
Some(Self { start, end })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Timeliness {
NotRequested,
LocalWindow,
RequestNonce,
Future,
OutsideWindow,
Unverified,
Uncertain(BoundUncertainty),
}
#[must_use]
pub fn timeliness(
reading: Reading,
accuracy: Option<Accuracy>,
utc: &LeapTable<'_>,
reference: Option<Instant>,
requested: bool,
nonce: Option<bool>,
window: Option<RequestWindow>,
) -> Timeliness {
let lower = earliest(reading, accuracy, utc);
if let (Some(reference), Ok(lower)) = (reference, lower)
&& lower > reference
{
return Timeliness::Future;
}
if let Some(window) = window {
match lower.and_then(|start| latest(reading, accuracy, utc).map(|end| (start, end))) {
Ok((start, end)) => {
if start < window.start || end > window.end {
return Timeliness::OutsideWindow;
}
return Timeliness::LocalWindow;
}
Err(reason) => {
if nonce == Some(true) {
return Timeliness::RequestNonce;
}
return Timeliness::Uncertain(reason);
}
}
}
if nonce == Some(true) {
return Timeliness::RequestNonce;
}
if requested {
return Timeliness::Unverified;
}
if reference.is_some() {
match lower {
Ok(_) => Timeliness::NotRequested,
Err(reason) => Timeliness::Uncertain(reason),
}
} else {
Timeliness::Unverified
}
}