diff --git a/proto/encode.go b/proto/encode.go index 98410a68..b294392f 100644 --- a/proto/encode.go +++ b/proto/encode.go @@ -47,6 +47,26 @@ type MarshalOptions struct { // detail and subject to change. Deterministic bool + // UseCachedSize indicates that the result of a previous Size call + // may be reused. + // + // Setting this option asserts that: + // + // 1. Size has previously been called on this message with identical + // options (except for UseCachedSize itself). + // + // 2. The message and all its submessages have not changed in any + // way since the Size call. + // + // If either of these invariants is broken, the results are undefined + // but may include panics or invalid output. + // + // Implementations MAY take this option into account to provide + // better performance, but there is no guarantee that they will do so. + // There is absolutely no guarantee that Size followed by Marshal with + // UseCachedSize set will perform equivalently to Marshal alone. + UseCachedSize bool + pragma.NoUnkeyedLiterals } @@ -93,6 +113,7 @@ func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error) copy(x, b) b = x } + o.UseCachedSize = true } return methods.MarshalAppend(b, m, protoiface.MarshalOptions(o)) } diff --git a/proto/size.go b/proto/size.go index a817cf7f..ab21cb34 100644 --- a/proto/size.go +++ b/proto/size.go @@ -13,6 +13,11 @@ import ( // Size returns the size in bytes of the wire-format encoding of m. func Size(m Message) int { + return MarshalOptions{}.Size(m) +} + +// Size returns the size in bytes of the wire-format encoding of m. +func (o MarshalOptions) Size(m Message) int { if size, err := sizeMessageFast(m); err == nil { return size } diff --git a/runtime/protoiface/methods.go b/runtime/protoiface/methods.go index e7d92db2..42832de0 100644 --- a/runtime/protoiface/methods.go +++ b/runtime/protoiface/methods.go @@ -27,10 +27,6 @@ type Methods struct { // Size returns the size in bytes of the wire-format encoding of m. Size func(m protoreflect.ProtoMessage) int - // CachedSize returns the result of the last call to Size. - // It must not be called if the message has been changed since the last call to Size. - CachedSize func(m protoreflect.ProtoMessage) int - // Unmarshal parses the wire-format message in b and places the result in m. // It does not reset m or perform required field checks. Unmarshal func(b []byte, m protoreflect.ProtoMessage, opts UnmarshalOptions) error @@ -55,6 +51,7 @@ const ( type MarshalOptions struct { AllowPartial bool Deterministic bool + UseCachedSize bool pragma.NoUnkeyedLiterals }