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

Support specifying the exact type path #371

Open
Veetaha opened this issue Sep 28, 2020 · 3 comments
Open

Support specifying the exact type path #371

Veetaha opened this issue Sep 28, 2020 · 3 comments

Comments

@Veetaha
Copy link
Contributor

Veetaha commented Sep 28, 2020

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

@danburkert
Copy link
Collaborator

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

@anelson
Copy link

anelson commented Nov 4, 2021

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?

@lytefast
Copy link
Contributor

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

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

4 participants