Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider dropping need for macro in place of traits and function pointers. #9

Closed
jkelleyrtp opened this issue Apr 14, 2021 · 1 comment

Comments

@jkelleyrtp
Copy link
Contributor

jkelleyrtp commented Apr 14, 2021

I use a similar pattern to the fn_handler proc macro in a crate that I'm working on and didn't want to require the user to annotate the function with a proc macro. Instead, I use this pattern:

struct Handler<F: Future<Output = ()>> {
    caller: fn(&mut Request, &mut Response, &mut Depot) -> F
}

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request, &mut Response, &mut Depot) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: self
         }
    }
} 

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request, &mut Response) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: |req, resp, _dep| self(req, resp)
         }
    }
} 

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: |req, _resp, _dep| self(req)
         }
    }
} 

//...etc for all combinations

You might need to add a lifetime annotation into the future generic, but this might let you skip the need for impl SalvoHandler. SalvoHandler would be directly impl for the Handler struct, which you can still treat as Box<dyn SalvoHandler>. To pass the handlers into the router, you would just accept impl into<Handler>.

However, I would suggest just sticking with a single type generic over the future, forcing req, resp, and depot to be part of every handler. It might be a bit ceremonious in boiler plate, but would be easy to copy-paste and forces consistency within a given codebase.

@driftluo
Copy link
Member

I tried to use simple proxy traits and macros to implement what salvo proc macro, but failed because, after multiple proxies, there was a problem with the lifetime judgment, and rustc does not recognize such operations.

I studied the realization of bevy, and it can be achieved, but I think it’s more complicated

Function pointers may be an option, but not sure at this time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants