tafia / quick-protobuf

A rust implementation of protobuf parser
MIT License
452 stars 87 forks source link

proto3: optional fields with default values not serialized #260

Open Wiezzel opened 5 months ago

Wiezzel commented 5 months ago

I have the following schema:

syntax = "proto3";
package messages;

message Query {
  optional string query_id = 1;
  optional string dataset = 2;
  optional string query = 3;
  optional bool profiling = 4;
  optional string client_state_json = 5;
  bytes signature = 6;
}

When I generate code with pb-rs, I'm getting the following implementation of write_message:

fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
    if self.query_id != String::default() { w.write_with_tag(10, |w| w.write_string(&**&self.query_id))?; }
    if self.dataset != String::default() { w.write_with_tag(18, |w| w.write_string(&**&self.dataset))?; }
    if self.query != String::default() { w.write_with_tag(26, |w| w.write_string(&**&self.query))?; }
    if self.profiling != false { w.write_with_tag(32, |w| w.write_bool(*&self.profiling))?; }
    if self.client_state_json != String::default() { w.write_with_tag(42, |w| w.write_string(&**&self.client_state_json))?; }
    if !self.signature.is_empty() { w.write_with_tag(50, |w| w.write_bytes(&**&self.signature))?; }
    Ok(())
}

It seems clear that default values are not being serialized. According to protobuf docs, fields marked with optional in proto3 should follow the explicit presence discipline which means:

Explicitly set values are always serialized, including default values.

I believe this should be fixed to conform to the specification.