prost
prost copied to clipboard
Support specifying the exact type path
As for now, prost supports adding attributes to types and fields by matching the prefix of the proto path. This works fine in most cases but this breaks when we have nested types that should not have the same attributes as their parent messages.
E.g.:
syntax = "proto2";
package issue;
message Foo {
// Suppose it is required for this enum be nested under Foo message
// and Foo message itself has to derive `Copy` or some other custom trait
// At the time of this writing we cannot achieve this via `type_attribute`
// because `NestedEnum` "inherits" all of the type attributes applied to the
// parent message
enum NestedEnum {
A = 0;
B = 1;
}
}
fn main() {
let mut cfg = prost_build::Config::new();
cfg.type_attribute(".issue.Foo", "#[derive(Copy)]");
cfg.compile_protos(&["issue.proto"], &[env!("CARGO_MANIFEST_DIR")]).unwrap();
}
To reproduce the problem clone and cargo build this repo here:
https://github.com/Veetaha/prost-prefix-proto-path-match-problem
Hi @Veetaha, I think this may be a dupe of #150, could you try the suggestion I made there?
Hi @danburkert, I work with @Veetaha and am having this same problem. I tried your proposed solution in the example project which @Veetaha posted. Something like this:
fn main() {
let mut cfg = prost_build::Config::new();
cfg.type_attribute(".issue.Foo", "#[derive(Copy)]");
// Don't apply the `derive(Copy)` attribute to the enum `NestedEnum`
cfg.type_attribute(".issue.Foo.NestedEnum", "");
cfg.compile_protos(&["issue.proto"], &[env!("CARGO_MANIFEST_DIR")]).unwrap();
}
This doesn't work. I looked at the prost-build code and it seems like it's specifically designed to apply every type_attribute entry to every type which matches, be it a global, full path, prefix, or suffix match. So the proposed solution won't work with the current implementation.
This is a really difficult limitation to overcome. We have some tooling which lets us annotate messages in our (pretty complex) Protobuf files with tags, and then for everything with that tag set a custom derive attribute. This completely breaks when a message contains an enum or oneof which is not compatible with that attribute.
We'd be happy to try to fix this in prost and submit a PR, but I'm not sure what kind of solution you'd be willing to accept. Any ideas?
+1 this also came up when I was trying to add unique derives to a nested enum:
message Key {
// Enum is only used here so it doesn't make sense to extract
enum Namespace {
DEFAULT = 0;
NAMESPACE_1 = 1;
}
Namespace namespace = 1;
Where my build.rs is:
let mut prost_config = prost_build::Config::default();
prost_config.type_attribute(
"issue.key.Namespace",
"#[derive(strum::IntoStaticStr)]",
);
This works if I extract Namespace from Key but the preference would be keep them nested.