1use crate::{send::SendFuture, EnvBinding, Result};
2use serde::{Deserialize, Serialize};
3use wasm_bindgen::{JsCast, JsValue};
4use wasm_bindgen_futures::JsFuture;
5use worker_sys::RateLimiter as RateLimiterSys;
6
7#[derive(Debug)]
8pub struct RateLimiter(RateLimiterSys);
9
10#[derive(Serialize, Deserialize)]
11struct RateLimitOptions {
12 key: String,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct RateLimitOutcome {
17 pub success: bool,
18}
19
20unsafe impl Send for RateLimiter {}
21unsafe impl Sync for RateLimiter {}
22
23impl EnvBinding for RateLimiter {
24 const TYPE_NAME: &'static str = "Ratelimit";
25}
26impl RateLimiter {
27 pub async fn limit(&self, key: String) -> Result<RateLimitOutcome> {
28 let arg = serde_wasm_bindgen::to_value(&RateLimitOptions { key })?;
29 let promise = self.0.limit(arg.into())?;
30 let fut = SendFuture::new(JsFuture::from(promise));
31 let result = fut.await?;
32 let outcome = serde_wasm_bindgen::from_value(result)?;
33 Ok(outcome)
34 }
35}
36
37impl JsCast for RateLimiter {
38 fn instanceof(val: &JsValue) -> bool {
39 val.is_instance_of::<RateLimiterSys>()
40 }
41
42 fn unchecked_from_js(val: JsValue) -> Self {
43 Self(val.into())
44 }
45
46 fn unchecked_from_js_ref(val: &JsValue) -> &Self {
47 unsafe { &*(val as *const JsValue as *const Self) }
48 }
49}
50
51impl From<RateLimiter> for JsValue {
52 fn from(limiter: RateLimiter) -> Self {
53 JsValue::from(limiter.0)
54 }
55}
56
57impl AsRef<JsValue> for RateLimiter {
58 fn as_ref(&self) -> &JsValue {
59 &self.0
60 }
61}
62
63impl From<RateLimiterSys> for RateLimiter {
64 fn from(inner: RateLimiterSys) -> Self {
65 Self(inner)
66 }
67}