use crate::data_context::{UsageBucket, UsageData};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum UsageWindow {
FiveHour,
SevenDay,
}
pub(crate) enum WindowResolution<'a> {
Endpoint(&'a UsageBucket),
JsonlTokens(u64),
}
pub(crate) enum ResetSource {
Endpoint(jiff::Timestamp),
JsonlBlockEnd(jiff::Timestamp),
}
impl UsageWindow {
pub(crate) fn resolve_percent<'a>(
self,
data: &'a UsageData,
) -> Result<WindowResolution<'a>, &'static str> {
match (self, data) {
(Self::FiveHour, UsageData::Endpoint(e)) => e
.five_hour
.as_ref()
.map(WindowResolution::Endpoint)
.ok_or("endpoint usage.five_hour absent"),
(Self::SevenDay, UsageData::Endpoint(e)) => e
.seven_day
.as_ref()
.map(WindowResolution::Endpoint)
.ok_or("endpoint usage.seven_day absent"),
(Self::FiveHour, UsageData::Jsonl(j)) => j
.five_hour
.as_ref()
.map(|w| WindowResolution::JsonlTokens(w.tokens.total()))
.ok_or("jsonl five_hour block inactive"),
(Self::SevenDay, UsageData::Jsonl(j)) => {
Ok(WindowResolution::JsonlTokens(j.seven_day.tokens.total()))
}
}
}
}
pub(crate) fn resolve_five_hour_reset(data: &UsageData) -> Result<ResetSource, &'static str> {
match data {
UsageData::Endpoint(e) => {
let bucket = e
.five_hour
.as_ref()
.ok_or("endpoint usage.five_hour absent")?;
bucket
.resets_at
.map(ResetSource::Endpoint)
.ok_or("five_hour.resets_at absent")
}
UsageData::Jsonl(j) => {
let window = j
.five_hour
.as_ref()
.ok_or("jsonl five_hour block inactive")?;
Ok(ResetSource::JsonlBlockEnd(window.ends_at()))
}
}
}
pub(crate) fn resolve_seven_day_reset(data: &UsageData) -> Result<jiff::Timestamp, &'static str> {
match data {
UsageData::Endpoint(e) => {
let bucket = e
.seven_day
.as_ref()
.ok_or("endpoint usage.seven_day absent")?;
bucket.resets_at.ok_or("seven_day.resets_at absent")
}
UsageData::Jsonl(_) => Err("jsonl fallback has no hard reset"),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::data_context::{EndpointUsage, JsonlUsage, SevenDayWindow, TokenCounts, UsageData};
#[test]
fn seven_day_reset_returns_err_under_jsonl() {
let data = UsageData::Jsonl(JsonlUsage::new(
None,
SevenDayWindow::new(TokenCounts::default()),
));
assert_eq!(
resolve_seven_day_reset(&data),
Err("jsonl fallback has no hard reset"),
);
}
#[test]
fn seven_day_reset_returns_err_when_endpoint_bucket_absent() {
let data = UsageData::Endpoint(EndpointUsage {
five_hour: None,
seven_day: None,
seven_day_opus: None,
seven_day_sonnet: None,
seven_day_oauth_apps: None,
extra_usage: None,
unknown_buckets: std::collections::HashMap::new(),
});
assert_eq!(
resolve_seven_day_reset(&data),
Err("endpoint usage.seven_day absent"),
);
}
}