1use std::sync::{Arc, RwLock};
2use std::time::Duration;
3
4use reqwest::header::HeaderMap;
5
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
8pub struct RateLimit {
9 pub limit: Option<u32>,
11 pub remaining: Option<u32>,
13 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 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}