prost icon indicating copy to clipboard operation
prost copied to clipboard

prost-build 0.8.0 regression: `field_attribute` on a oneof field gets added to enum variants

Open appaquet opened this issue 4 years ago • 5 comments

Adding field attributes on oneof fields in prost-build 0.8.0 also adds the attributes to the enum variants. In this example, adding #[serde(flatten)] to TestMessage.some_field correctly adds the attribute to the TestMessage.some_field field of the struct, but also adds the attribute to each enum variant.

proto

syntax = "proto3";

package test;

message TestMessage {
    oneof some_field {
        string a_field = 1;
        string b_field = 2;
    }
}

build.rs

    prost_build::Config::new()
        .type_attribute("TestMessage", "#[derive(Serialize, Deserialize)]")
        .type_attribute(
            "TestMessage.some_field",
            "#[derive(Serialize, Deserialize)]",
        )
        .field_attribute("TestMessage.some_field", "#[serde(flatten)]")
        .compile_protos(&vec!["./protos/test.proto"], &["./protos/"])
        .expect("prost error");

Outputs:

#[derive(Serialize, Deserialize)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct TestMessage {
    #[prost(oneof="test_message::SomeField", tags="1, 2")]
    #[serde(flatten)]
    pub some_field: ::core::option::Option<test_message::SomeField>,
}
/// Nested message and enum types in `TestMessage`.
pub mod test_message {
    #[derive(Serialize, Deserialize)]
    #[derive(Clone, PartialEq, ::prost::Oneof)]
    pub enum SomeField {
        #[prost(string, tag="1")]
        #[serde(flatten)]
        AField(::prost::alloc::string::String),
        #[prost(string, tag="2")]
        #[serde(flatten)]
        BField(::prost::alloc::string::String),
    }
}

Notice the extra #[serde(flatten)] on each variant. This results in unknown serde variant attribute flatten since serde macro gets wrongly added to the enum variants.

appaquet avatar Jul 10 '21 13:07 appaquet

Fixed in #522

LucioFranco avatar Sep 15 '21 20:09 LucioFranco

This issue does not appear to be fixed. It still happens to me in master.

wagenet avatar Feb 17 '22 00:02 wagenet

Is this an example of the same issue:

syntax="proto3";

package api;
message Init {
    string msg_id = 1;
    message SetOs {
        enum OS {
            OS_UNKNOWN = 0;
            OS_WIN     = 1;
            OS_MAC     = 2;
        }
        OS     os_type = 2;
    }
    oneof Command {
        SetOs os_cmd        = 3;
    }
}

when I use the following code (build.rs)

    let mut config = prost_build::Config::new();
    config.type_attribute(".", "#[derive(serde::Deserialize, serde::Serialize)]");    
    config.field_attribute(".api.Init.SetOs", "#[serde(default)]");
    config.compile_protos(&["test_enum.proto"], &["../Proto"])

Then the variants of the enum also get attribute #[serde(default)].

pub mod init {
    // ...
    pub mod set_os {
        // ...
        #[repr(i32)]
        pub enum Os {
            #[serde(default)]
            Unknown = 0,
            #[serde(default)]
            Win = 1,
            #[serde(default)]
            Mac = 2,
        }
        impl Os {

markmmm avatar Feb 11 '23 06:02 markmmm

hello, this is still an issue. Is there any update on this?

jszwec avatar Mar 27 '25 02:03 jszwec

@jszwec This issue needs someone to take the lead, finds a good solution and submits a PR. Feel free to take that role.

caspermeijn avatar Apr 11 '25 13:04 caspermeijn