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

add support for proto2 groups #743

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

kristopherbullinger
Copy link

Hello. Thanks for your work on this repo. I'm interested in maximizing support for protobufs in rust.

In the interest of increasing protobuf conformance score, this pull request adds support for the deprecated proto2 group syntax.

Groups are generated similarly to messages; a rust struct is created to match the contents of the group.

Groups use a delimited merge operation when reading from a CodedInputStream. To avoid making a change to the public Message trait, an inherent method is generated in each group- and message-derived struct called merge_delimited, which takes an end_tag, and merges into the struct until that end tag is found. The Message impl for a struct leverages the inherent merge_delimited method on its message field for groups. Example:

syntax = "proto2";
message Foo {
  repeated group Data = 1 {
    optional int32 group_int32 = 2;
    required uint32 group_uint32 = 3;
  }
}
    // <Foo as Message>::merge_from
    pub fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 
        while let Some(tag) = is.read_raw_tag_or_eof()? {
            match tag {
                11 => {
                    let end_tag = ::protobuf::rt::set_wire_type_to_end_group(tag);
                    let mut data = foo::Data::default();
                    data.merge_delimited(is, end_tag)?; // <-- `foo::Data::merge_delimited` inherent method
                    self.data.push(data);
                },

When an unknown type is encountered, if the tag is of type StartGroup, a CodedOutputStream is created on top of a Vec<u8>, and all values are written to it until the corresponding end tag is found. The CodedOutputStream is then flushed, and the raw bytes returned for storage.

The computed serialized size of a group is the size of the message plus twice the size of the tag.

Generated code compiles with repeated, required, and optional groups.

This pull request addresses and provides a fix for Issue#742.

This feature addition covers a large surface area and I am happy to incorporate any feedback. Please let me know if I missed anything or if my implementation does not suit the coding style of this project.

@kristopherbullinger
Copy link
Author

Lots of tests are failing in the test-crates which I didn't use at first. I'll work on getting them to pass.

@kristopherbullinger
Copy link
Author

All of the tests are passing in each of the test crates. I think the remaining CI failures have something to do with the protobuf/regenerate.sh commands. Maybe you can help me get this over the finish line?

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

Successfully merging this pull request may close these issues.

1 participant