runtime/protoiface: API adjustments
The following adjustments were made:
* The pragma.NoUnkeyedLiterals is moved to be the first field.
This is done to keep the options struct smaller. Even if the last
field is zero-length, Go GC implementation details forces the struct
to be padded at the end.
* Methods are documented as always treating AllowPartial as true.
* Added a support flag for UnmarshalOptions.DiscardUnknown.
Change-Id: I1f75d226542ab2bb0123d9cea143c7060df226d8
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/185998
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/encode.go b/proto/encode.go
index f9a753b..bc7da0c 100644
--- a/proto/encode.go
+++ b/proto/encode.go
@@ -19,6 +19,8 @@
// Example usage:
// b, err := MarshalOptions{Deterministic: true}.Marshal(m)
type MarshalOptions struct {
+ pragma.NoUnkeyedLiterals
+
// AllowPartial allows messages that have missing required fields to marshal
// without returning an error. If AllowPartial is false (the default),
// Marshal will return an error if there are any missing required fields.
@@ -31,6 +33,8 @@
// the same message will return the same bytes, and that different
// processes of the same binary (which may be executing on different
// machines) will serialize equal messages to the same bytes.
+ // It has no effect on the resulting size of the encoded message compared
+ // to a non-deterministic marshal.
//
// Note that the deterministic serialization is NOT canonical across
// languages. It is not guaranteed to remain stable over time. It is
@@ -64,8 +68,6 @@
// There is absolutely no guarantee that Size followed by Marshal with
// UseCachedSize set will perform equivalently to Marshal alone.
UseCachedSize bool
-
- pragma.NoUnkeyedLiterals
}
var _ = protoiface.MarshalOptions(MarshalOptions{})
@@ -83,15 +85,11 @@
// MarshalAppend appends the wire-format encoding of m to b,
// returning the result.
func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
- // Set AllowPartial in recursive calls to marshal to avoid duplicating
- // effort with the single initialization check below.
- allowPartial := o.AllowPartial
- o.AllowPartial = true
out, err := o.marshalMessage(b, m.ProtoReflect())
if err != nil {
return nil, err
}
- if allowPartial {
+ if o.AllowPartial {
return out, nil
}
return out, IsInitialized(m)
@@ -99,16 +97,14 @@
func (o MarshalOptions) marshalMessage(b []byte, m protoreflect.Message) ([]byte, error) {
if methods := protoMethods(m); methods != nil && methods.MarshalAppend != nil &&
- !(o.Deterministic && methods.Flags&protoiface.MethodFlagDeterministicMarshal == 0) {
- if methods.Size != nil {
- sz := methods.Size(m)
- if cap(b) < len(b)+sz {
- x := make([]byte, len(b), len(b)+sz)
- copy(x, b)
- b = x
- }
- o.UseCachedSize = true
+ !(o.Deterministic && methods.Flags&protoiface.SupportMarshalDeterministic == 0) {
+ sz := methods.Size(m, protoiface.MarshalOptions(o))
+ if cap(b) < len(b)+sz {
+ x := make([]byte, len(b), len(b)+sz)
+ copy(x, b)
+ b = x
}
+ o.UseCachedSize = true
return methods.MarshalAppend(b, m, protoiface.MarshalOptions(o))
}
return o.marshalMessageSlow(b, m)