tokio-rs / prost

PROST! a Protocol Buffers implementation for the Rust Language
Apache License 2.0
3.78k stars 489 forks source link

prost-build: Allow path globbing for type and field attributes #987

Open munic-mabs opened 6 months ago

munic-mabs commented 6 months ago

Hi,

We'd like to have the ability to add an attribute to multiple types of the same nature. An example would be to derive a custom proc-macro for all of our Response types. Currently, it is done manually as follows.

let mut conf = prost_build::Config::new();
conf.type_attribute("LoadStackResponse", "#[derive(custom::FromStatus)]");
conf.type_attribute("DropStackResponse", "#[derive(custom::FromStatus)]");
conf.type_attribute("ListStacksResponse", "#[derive(custom::FromStatus)]");
conf.type_attribute("ListStacksResponse", "#[derive(custom::FromStatus)]");

Ideally we'd be able to do something like this.

let mut conf = prost_build::Config::new();
conf.type_attribute_glob(".*Response", "#[derive(custom::FromStatus)]");

I am not aware of any pre-existing convention/implementation concerning the globbing of Protobuf paths. It'd be interesting to be able to also support more specific cases such as .a.b.*.*Response which would match .a.b.c.MyResponse.


Points that might be interesting to discuss.

  1. What if two glob patterns, i.e., two type_attribute calls, match a given type. What would the expected behavior in this case? I believe that the current behavior of type_attribute preserves only one, possibly the last, entry?

  2. How can one exclude one or more types/attributes from a globbing pattern?

  3. Is it possible to have a publicly accessible API to retrieve the result of glob expansion for debugging purposes?

  4. While it seems more complex, an alternative implementation could offer the ability to inject custom logic to be executed for each message parsed by prost similarly to ServiceGenerator assuming it does not exist already.

Thank you!

caspermeijn commented 6 months ago

Hi @munic-mabs

I don't want to blow off your idea, but I think globbing becomes complicated really fast. You can already see that in the questions you ask đŸ˜‰

Did you know type_attribute can match on all messages in a package? Maybe you can reorganize the message to do a single match?

I think the best way to get this done in prost upstream is to work on it yourself. You might want to look at PathMap struct. This struct does the actual matching. Perhaps you could build a prototype so that we have a better idea of your solution.

https://github.com/tokio-rs/prost/blob/0a64a09158eee89f04700b5761c474d9feb11a16/prost-build/src/path.rs#L7C19-L7C26