prost icon indicating copy to clipboard operation
prost copied to clipboard

Support specifying the exact type path

Open Veetaha opened this issue 5 years ago • 3 comments

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

Veetaha avatar Sep 28 '20 14:09 Veetaha

Hi @Veetaha, I think this may be a dupe of #150, could you try the suggestion I made there?

danburkert avatar Dec 31 '20 20:12 danburkert

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?

anelson avatar Nov 04 '21 15:11 anelson

+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.

lytefast avatar Jan 26 '22 20:01 lytefast