Hi all,
I'm in the early stages of writing a decorator-like proc_macro_attribute that does rate limiting on the method it's attached to, and am trying to avoid some headaches I see down the line. I've seen there's a few rate limiters out there, but none have the semantics (or method and not just function support) I'm looking for. The methods being wrapped would potentially be async methods (but I've omitted in examples), and I'll probably end up using darling so I have better semantics in the attribute arguments down the line.
The idea is to have something like:
pub struct Caller { ... }
impl Caller {
#[rate_limit(Duration::seconds(5), 3)]
fn call_api(&self, a: A, b: B) -> Response { ... }
}
which would rate-limit the function to 3 calls per 5 seconds. From what I've done before, this seems doable, but the hiccup I see is that when replacing the implementation with an outer function and inner function, I will have to parse &self, a: A, b: B
and convert it to self: &Self, a: A, b: B
, since &self
wouldn't be valid within the inner function signature. Is this assumption correct? E.g., this would not work:
// generated code returned by proc_macro_attribute
fn call_api(&self, a: A, b: B) -> Response {
fn __inner_call_api(&self, a: A, b: B) -> Response { ... }
// ^^^^ Am I wrong in thinking this will be invalid to define this with &self here?
// do some rate limiting stuff and maybe wait some time
__inner_call_api(&self, a, b)
}
If all the above is more or less correct, it seems like the two options are to:
- Do the signature/argument parsing for the inner function, and convert
&self
toself: &Self
and pass it in, which is doable (I think), but probably not that fun, or, - Move the
__inner_call_api
copy of the wrapped method to the impl block itself to avoid the &self issue, but this pollutes the namespace of the impl block, and gives the caller the ability to call__inner_call_api
directly and bypass rate limiting if they wanted.
Are my assumptions completely off-base, or is there some easier solution I'm not thinking of? This would be used extensively within a crate, so a decorator-like attribute macro seems like the choice, but I understand it's not easy since I've hard a time even finding examples of similar things being done.
Thanks in advance for any help!