rust-protobuf
rust-protobuf copied to clipboard
Customized generation of sub-modules
generated rust stubs for oneof and nested messages generate sub-modules to namespace the types, however the generated structs and enums in the sub-modules aren't customized.
For example
message ExampleMessageWithOneof {
oneof selection {
string string_field = 1;
bool bool_field = 2;
int32 int_field = 3;
ExampleTopLevelEnum enum_field = 4;
ExampleMessageWithNestedMessage message_field = 5;
google.protobuf.Empty empty_field = 6;
}
}
with
impl CustomizeCallback for SerdeSerializeDeserialize {
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 {
match field.proto().type_() {
Type::TYPE_ENUM => {
Customize::default().before(
"#[serde(serialize_with = \"::protobuf_serde_helpers::serialize_enum_or_unknown\", deserialize_with = \"::protobuf_serde_helpers::deserialize_enum_or_unknown\")]")
}
// refer to https://serde.rs/remote-derive.html
Type::TYPE_MESSAGE => Customize::default().before("#[serde(with=\"::protobuf_serde_helpers::MessageFieldDef\")]"),
_ => Customize::default(),
}
}
fn special_field(&self, _message: &MessageDescriptor, _field: &str) -> Customize {
Customize::default().before("#[serde(skip)]")
}
}
generates
#[derive(PartialEq,Clone,Default,Debug)]
#[derive(::serde::Serialize, ::serde::Deserialize)]
// @@protoc_insertion_point(message:x.proto.ExampleMessageWithOneof)
pub struct ExampleMessageWithOneof {
// message oneof groups
pub selection: ::std::option::Option<example_message_with_oneof::Selection>,
// special fields
#[serde(skip)]
// @@protoc_insertion_point(special_field:x.proto.ExampleMessageWithOneof.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
pub mod example_message_with_oneof {
#[derive(Clone,PartialEq,Debug)]
#[non_exhaustive]
// @@protoc_insertion_point(oneof:x.proto.ExampleMessageWithOneof.selection)
pub enum Selection {
// @@protoc_insertion_point(oneof_field:x.proto.ExampleMessageWithOneof.string_field)
StringField(::std::string::String),
// @@protoc_insertion_point(oneof_field:x.proto.ExampleMessageWithOneof.bool_field)
BoolField(bool),
// @@protoc_insertion_point(oneof_field:x.proto.ExampleMessageWithOneof.int_field)
IntField(i32),
// @@protoc_insertion_point(oneof_field:x.proto.ExampleMessageWithOneof.enum_field)
EnumField(::protobuf::EnumOrUnknown<super::ExampleTopLevelEnum>),
// @@protoc_insertion_point(oneof_field:x.proto.ExampleMessageWithOneof.message_field)
MessageField(super::ExampleMessageWithNestedMessage),
}
...
}
which fails with
error[E0277]: the trait bound `Selection: Deserialize<'_>` is not satisfied
--> x/proto/example_rust_proto_pb_rs/example.rs:1048:5
|
1048 | pub selection: ::std::option::Option<example_message_with_oneof::Selection>,
| ^^^ the trait `Deserialize<'_>` is not implemented for `Selection`
|
= note: required because of the requirements on the impl of `Deserialize<'_>` for `std::option::Option<Selection>`
There are similar issues with nested messages and enums:
message ExampleMessageWithNestedMessage {
message ExampleNestedMessage {
int32 value = 1;
}
ExampleNestedMessage nested_message = 1;
}
message ExampleMessageWithEnum {
enum ExampleNestedEnum {
EXAMPLE_NESTED_ENUM_UNSPECIFIED = 0;
EXAMPLE_NESTED_ENUM_A = 1;
}
ExampleTopLevelEnum enum1 = 1;
ExampleNestedEnum enum2 = 2;
}
From my experience, I just add definition of oneof
into your CustomizeCallback struct in build.rs
, which perhaps fix your error for now.
Like this,
fn oneof(&self, _oneof: &OneofDescriptor) -> Customize {
Customize::default()
.before("#[derive(::serde::Serialize, ::serde::Deserialize)]\n#[serde(untagged)]")
}
But over that, I also get errors on Serialize
, Deserialize
not implemented for EnumOrUnknown<_>
. I cannot add things like serde attribute macro for enum variant or whatever. E.g:
#[derive(Clone,PartialEq,Debug)]
#[non_exhaustive]
#[derive(::serde::Serialize, ::serde::Deserialize)]
#[serde(untagged)]
// @@protoc_insertion_point(oneof:ShapeType.type)
pub enum Type {
// @@protoc_insertion_point(oneof_field:ShapeType.Rectangle)
Rectangle(f64),
// @@protoc_insertion_point(oneof_field:ShapeType.Square)
Square(f64),
// @@protoc_insertion_point(oneof_field:ShapeType.Circle)
Circle(f64),
// @@protoc_insertion_point(oneof_field:ShapeType.wall)
Wall(::protobuf::EnumOrUnknown<super::Wall>),
}
impl ::protobuf::Oneof for Type {
}
impl ::protobuf::OneofFull for Type {
fn descriptor() -> ::protobuf::reflect::OneofDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::OneofDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| <super::ShapeType as ::protobuf::MessageFull>::descriptor().oneof_by_name("type").unwrap()).clone()
}
}
impl Type {
pub(in super) fn generated_oneof_descriptor_data() -> ::protobuf::reflect::GeneratedOneofDescriptorData {
::protobuf::reflect::GeneratedOneofDescriptorData::new::<Type>("type")
}
}
Errors:
1264 | #[derive(::serde::Serialize, ::serde::Deserialize)]
| ^^^^^^^^^^^^^^^^^^ the trait `Serialize` is not implemented for `EnumOrUnknown<Wall>`
...
1275 | Wall(::protobuf::EnumOrUnknown<super::Wall>),
| - required by a bound introduced by this call
1275 | Wall(::protobuf::EnumOrUnknown<super::Wall>),
| ^ the trait `parse_proto::_::_serde::Deserialize<'_>` is not implemented for `EnumOrUnknown<Wall>`