Skip to main content

hypixel/
ratelimit.rs

1use std::sync::{Arc, RwLock};
2use std::time::Duration;
3
4use reqwest::header::HeaderMap;
5
6/// A snapshot of the rate-limit state reported by the API on the last response.
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
8pub struct RateLimit {
9    /// Maximum number of requests permitted in the current window.
10    pub limit: Option<u32>,
11    /// Requests remaining in the current window.
12    pub remaining: Option<u32>,
13    /// Seconds until the current window resets.
14    pub reset: Option<u64>,
15}
16
17impl RateLimit {
18    pub(crate) fn from_headers(headers: &HeaderMap) -> Self {
19        fn parse<T: std::str::FromStr>(headers: &HeaderMap, name: &str) -> Option<T> {
20            headers
21                .get(name)
22                .and_then(|v| v.to_str().ok())
23                .and_then(|v| v.trim().parse().ok())
24        }
25        RateLimit {
26            limit: parse(headers, "ratelimit-limit"),
27            remaining: parse(headers, "ratelimit-remaining"),
28            reset: parse(headers, "ratelimit-reset"),
29        }
30    }
31
32    /// Duration until the current window resets, if known.
33    pub fn reset_after(&self) -> Option<Duration> {
34        self.reset.map(Duration::from_secs)
35    }
36}
37
38#[derive(Debug, Clone, Default)]
39pub(crate) struct SharedRateLimit(Arc<RwLock<RateLimit>>);
40
41impl SharedRateLimit {
42    pub(crate) fn store(&self, value: RateLimit) {
43        if let Ok(mut guard) = self.0.write() {
44            *guard = value;
45        }
46    }
47
48    pub(crate) fn load(&self) -> RateLimit {
49        self.0.read().map(|g| *g).unwrap_or_default()
50    }
51}