stepancheg / rust-protobuf

Rust implementation of Google protocol buffers
MIT License
2.81k stars 381 forks source link

Submessage generate issue when trying to add Serde support #645

Open curiousmindflow opened 2 years ago

curiousmindflow commented 2 years ago

Hello,

I have a .proto that rely on two other .proto, aka submessage. I need the corresponding generated .rs struct to be Serialize and Deserialize. For simple messages, it works already, but for message with submessage i have errors.

error[E0277]: the trait bound `MessageField<generated_with_pure::Point::Point>: Serialize` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:34:5
     |
34   |     pub position: ::protobuf::MessageField<super::Point::Point>,
     |     ^^^ the trait `Serialize` is not implemented for `MessageField<generated_with_pure::Point::Point>`
     |
     = help: the following other types implement trait `Serialize`:
               &'a T
               &'a mut T
               ()
               (T0, T1)
               (T0, T1, T2)
               (T0, T1, T2, T3)
               (T0, T1, T2, T3, T4)
               (T0, T1, T2, T3, T4, T5)
             and 215 others
note: required by a bound in `generated_with_pure::AMessage::_::_serde::ser::SerializeStruct::serialize_field`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/ser/mod.rs:1899:12
     |
1899 |         T: Serialize;
     |            ^^^^^^^^^ required by this bound in `generated_with_pure::AMessage::_::_serde::ser::SerializeStruct::serialize_field`

error[E0277]: the trait bound `MessageField<generated_with_pure::Eulerangles::Eulerangles>: Serialize` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:36:5
     |
36   |     pub angles: ::protobuf::MessageField<super::Eulerangles::Eulerangles>,
     |     ^^^ the trait `Serialize` is not implemented for `MessageField<generated_with_pure::Eulerangles::Eulerangles>`
     |
     = help: the following other types implement trait `Serialize`:
               &'a T
               &'a mut T
               ()
               (T0, T1)
               (T0, T1, T2)
               (T0, T1, T2, T3)
               (T0, T1, T2, T3, T4)
               (T0, T1, T2, T3, T4, T5)
             and 215 others
note: required by a bound in `generated_with_pure::AMessage::_::_serde::ser::SerializeStruct::serialize_field`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/ser/mod.rs:1899:12
     |
1899 |         T: Serialize;
     |            ^^^^^^^^^ required by this bound in `generated_with_pure::AMessage::_::_serde::ser::SerializeStruct::serialize_field`

error[E0277]: the trait bound `MessageField<generated_with_pure::Point::Point>: Deserialize<'_>` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:34:5
     |
34   |     pub position: ::protobuf::MessageField<super::Point::Point>,
     |     ^^^ the trait `Deserialize<'_>` is not implemented for `MessageField<generated_with_pure::Point::Point>`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               <&'a Path as Deserialize<'de>>
               <&'a [u8] as Deserialize<'de>>
               <&'a str as Deserialize<'de>>
               <() as Deserialize<'de>>
               <(T0, T1) as Deserialize<'de>>
               <(T0, T1, T2) as Deserialize<'de>>
               <(T0, T1, T2, T3) as Deserialize<'de>>
               <(T0, T1, T2, T3, T4) as Deserialize<'de>>
             and 304 others
note: required by a bound in `next_element`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/de/mod.rs:1730:12
     |
1730 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `next_element`

error[E0277]: the trait bound `MessageField<generated_with_pure::Eulerangles::Eulerangles>: Deserialize<'_>` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:36:5
     |
36   |     pub angles: ::protobuf::MessageField<super::Eulerangles::Eulerangles>,
     |     ^^^ the trait `Deserialize<'_>` is not implemented for `MessageField<generated_with_pure::Eulerangles::Eulerangles>`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               <&'a Path as Deserialize<'de>>
               <&'a [u8] as Deserialize<'de>>
               <&'a str as Deserialize<'de>>
               <() as Deserialize<'de>>
               <(T0, T1) as Deserialize<'de>>
               <(T0, T1, T2) as Deserialize<'de>>
               <(T0, T1, T2, T3) as Deserialize<'de>>
               <(T0, T1, T2, T3, T4) as Deserialize<'de>>
             and 304 others
note: required by a bound in `next_element`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/de/mod.rs:1730:12
     |
1730 |         T: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `next_element`

error[E0277]: the trait bound `MessageField<generated_with_pure::Point::Point>: Deserialize<'_>` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:34:5
     |
34   |     pub position: ::protobuf::MessageField<super::Point::Point>,
     |     ^^^ the trait `Deserialize<'_>` is not implemented for `MessageField<generated_with_pure::Point::Point>`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               <&'a Path as Deserialize<'de>>
               <&'a [u8] as Deserialize<'de>>
               <&'a str as Deserialize<'de>>
               <() as Deserialize<'de>>
               <(T0, T1) as Deserialize<'de>>
               <(T0, T1, T2) as Deserialize<'de>>
               <(T0, T1, T2, T3) as Deserialize<'de>>
               <(T0, T1, T2, T3, T4) as Deserialize<'de>>
             and 304 others
note: required by a bound in `next_value`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/de/mod.rs:1869:12
     |
1869 |         V: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `next_value`

error[E0277]: the trait bound `MessageField<generated_with_pure::Eulerangles::Eulerangles>: Deserialize<'_>` is not satisfied
    --> /home/alex/dev/tokio-dds-bindings/target/debug/build/tokio-dds-bindings-45205a48c4e1b619/out/generated_with_pure/Poseeuler.rs:36:5
     |
36   |     pub angles: ::protobuf::MessageField<super::Eulerangles::Eulerangles>,
     |     ^^^ the trait `Deserialize<'_>` is not implemented for `MessageField<generated_with_pure::Eulerangles::Eulerangles>`
     |
     = help: the following other types implement trait `Deserialize<'de>`:
               <&'a Path as Deserialize<'de>>
               <&'a [u8] as Deserialize<'de>>
               <&'a str as Deserialize<'de>>
               <() as Deserialize<'de>>
               <(T0, T1) as Deserialize<'de>>
               <(T0, T1, T2) as Deserialize<'de>>
               <(T0, T1, T2, T3) as Deserialize<'de>>
               <(T0, T1, T2, T3, T4) as Deserialize<'de>>
             and 304 others
note: required by a bound in `next_value`
    --> /home/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.138/src/de/mod.rs:1869:12
     |
1869 |         V: Deserialize<'de>,
     |            ^^^^^^^^^^^^^^^^ required by this bound in `next_value`

Here are the messages:

syntax = "proto3";

message Point {
    double x = 1;
    double y = 2;
    double z = 3;
}

syntax = "proto3";

message Eulerangles {
    float yaw = 1;
    float pitch = 2;
    float roll = 3;
}

syntax = "proto3";

import "Point.proto";
import "Eulerangles.proto";

message Poseeuler {
    Point position = 1;
    Eulerangles angles = 2;
}
GeorgeHahn commented 1 year ago

I'm curious if anyone has gotten this to work. I'm not sure that it's possible for a complex set of messages.

I'm attempting to add serde to the librespot_protocol protos. This worked perfectly with the previous serde feature. Here's about where I gave up:

impl protobuf_codegen::CustomizeCallback for AddSerde {
    fn message(&self, _message: &MessageDescriptor) -> Customize {
        Customize::default().before("#[derive(::serde::Serialize, ::serde::Deserialize)]")
    }

    fn enumeration(&self, _enum: &EnumDescriptor) -> Customize {
        Customize::default().before("#[derive(::serde::Serialize, ::serde::Deserialize)]")
    }

    fn field(&self, field: &FieldDescriptor) -> Customize {
        if field.proto().type_() == Type::TYPE_ENUM {
            if field.is_singular() {
                // singular optional enums
                if field.proto().proto3_optional()
                    || field.proto().descriptor_dyn().file_descriptor().syntax() == Syntax::Proto2
                        && field.proto().label() == Label::LABEL_OPTIONAL
                {
                    Customize::default()
                .before(
                    "#[serde(serialize_with = \"crate::optional_serialize_enum_or_unknown\", deserialize_with = \"crate::optional_deserialize_enum_or_unknown\")]")
                } else {
                    // singular required enums
                    Customize::default()
            .before(
                "#[serde(serialize_with = \"crate::serialize_enum_or_unknown\", deserialize_with = \"crate::deserialize_enum_or_unknown\")]")
                }
            } else {
                // repeated enums
                Customize::default()
                .before(
                    "#[serde(serialize_with = \"crate::vec_serialize_enum_or_unknown\", deserialize_with = \"crate::vec_deserialize_enum_or_unknown\")]")
            }
        } else if field.proto().type_() == Type::TYPE_MESSAGE && field.is_singular() {
            // messages
            Customize::default().before("#[serde(with = \"crate::MessageFieldDef\")]")
        } else {
            Customize::default()
        }
    }

    fn special_field(&self, _message: &MessageDescriptor, _field: &str) -> Customize {
        Customize::default().before("#[serde(skip)]")
    }

    // fn oneof(&self, _oneof: &OneofDescriptor) -> Customize {
    //     todo!("other issues note this may also be necessary")
    // }
}
svanharmelen commented 10 months ago

@GeorgeHahn did you ever managed to get it working? Have a challenging case myself and am running into issues for a message oneof groups field and two fields of type MessageField<T>... If you have any suggestions or references that would be awesome!

GeorgeHahn commented 10 months ago

Nope, I'm stranded on version 2 of the library.

svanharmelen commented 10 months ago

Hmm... I didn't even try version 2, but guess I'm doomed to do the same 😉

Thanks for your reply!!