reflect/prototype: make extensions use proto2 semantics for IsPacked

Extensions are normally thought of as a proto2 feature.
However, proto3 actually allows declarations of field extensions *only*
if they extend messages declared in descriptor.proto.

In such a situation it is not well defined whether the extension field
operates under proto2 or proto3 properties.

In some ways, such declarations are proto3-like.
For example, the declaration in the proto file still follows
proto3's syntactical grammar (e.g., no "optional" label required)
and proto3 semantics (e.g., default values are not allowed).

However, in other ways, such declarations are proto2-like.
For example, a repeated field of numeric scalars is not automatically packed.
This property is determined by the following test.

Compile the following proto file:

	syntax = "proto3";
	import "google/protobuf/descriptor.proto";
	extend google.protobuf.FieldOptions {
		repeated sint32 test_field = 20181023;
	}

then compile and run a C++ program with the following snippet:

	google::protobuf::FieldOptions m;
	m.AddExtension(test_field, 1);
	m.AddExtension(test_field, 2);
	m.AddExtension(test_field, 3);
	fstream output("out", ios::out | ios::trunc | ios::binary);
	m.SerializeToOstream(&output);

which produces an "out" file with the following contents:

	$ pbdump -sints 20181023 out
	Message{
		Tag{20181023, Varint}, Svarint(1),
		Tag{20181023, Varint}, Svarint(2),
		Tag{20181023, Varint}, Svarint(3),
	}

which is indicative that packed encoding was not used by default (proto2-like).
If we repeat the above experiment and explicit set "[packed = true]",
then packed encoding is used:

	$ pbdump -sints 20181023 out
	Message{
		Tag{20181023, Bytes}, LengthPrefix{Svarint(1), Svarint(2), Svarint(3)},
	}

Note that this change does not mean that field extensions are always proto2
since the experiment above does not conclusively prove that. Thus, the Syntax
on extensions derived from the descriptor protos may still report proto3.

The behavior of packed encoding with regards to proto3 says:

	In proto3, repeated fields of scalar numeric types use packed encoding by default.

One way to interpret this is:

	In proto3 (messages), repeated fields of scalar numeric types use packed encoding by default.

In which case packedness is a property of the message's syntax
rather than the field's syntax (if such a distinction exists).
Since only proto2 messages can be extended, we can safely assume that all
extension fields use proto2 semantics for IsPacked.

Change-Id: Iae595c6d88c6e252cae7552cae083bad42f2494a
Reviewed-on: https://go-review.googlesource.com/c/144278
Reviewed-by: Damien Neil <dneil@google.com>
1 file changed
tree: b941af80074cbad75e46edd79378ce693829b9a7
  1. cmd/
  2. internal/
  3. protogen/
  4. reflect/
  5. .gitignore
  6. .travis.yml
  7. AUTHORS
  8. CONTRIBUTING.md
  9. CONTRIBUTORS
  10. go.mod
  11. go.sum
  12. LICENSE
  13. PATENTS
  14. README.md
  15. regenerate.bash
  16. test.bash
README.md

Next Generation Go Protocol Buffers

WARNING: This repository is in active development. There are no guarantees about API stability. Breaking changes will occur until a stable release is made and announced.

This repository is for the development of the next major Go implementation of protocol buffers. This library makes breaking API changes relative to the existing Go protobuf library. Of particular note, this API aims to make protobuf reflection a first-class feature of the API and implements the protobuf ecosystem in terms of reflection.

Design Documents

List of relevant design documents:

Contributing

We appreciate community contributions. See CONTRIBUTING.md.

Reporting Issues

Issues regarding the new API can be filed at github.com/golang/protobuf. Please use a APIv2: prefix in the title to make it clear that the issue is regarding the new API work.