Search code examples
design-patternsrustactix-webbevy

How does seemingly variadic function work as in Actix-web and Bevy?


Ok, I know it is not really a variadic function, but I do not know how to specify it more clearly in the title.

Both Actix-web (Route::to) and Bevy (App::add_system) have functions which accept a variable number of arguments. I would very much like to know:

  • how is this (Rust) design pattern called?
  • how does it work? For example, how does Actix-web 'know' that to has been passed a function with a Query and perhaps a Path type?

All I could find out is that the function should implement a type (Handler<>/InfoSystemDescriptor<>), but in the case of Handler<>, only tuples implement it.


Solution

  • how is this (Rust) design pattern called?

    I don't think there is a special name, but it is using macros (although not necessary, just to reduce repetition) to implement a trait over all functions with N arguments, for example Handler in the case of Actix or InfoSystemDescriptor in the case of Bevy.

    but in the case of Handler<>, only tuples implement it.

    No. It is implemented for functions (you can see the Func generic parameter in each impl that has a Fn(...) bound), with the generic parameter Args set for their argument types as a tuple.

    The way they pass information about the function depends on the actual case, but it's usually some sort of trait method. For example, in actix-web, Args (the tuple of the parameter types) must implement FromRequest, and this is forwarded using bunch of blanket implementations to each of the arguments, so eventually each argument gets parsed using its FromRequest impl, and that is passed to the function via Handler::call(). Similarly, the return type is required to implement Responder.