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