proto: enable/disable fast path with build tags

Remove the Reflection field from MarshalOptions and UnmarshalOptions.
Disable the fast path and use the reflection-based implementation when
the 'protoreflect' build tag is set.

Change-Id: Ic674e3af67501de27fb03ec2712fbed40eae7fef
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/170896
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Damien Neil 2019-04-05 14:33:10 -07:00
parent 8fa64d98d8
commit cc2b078f98
7 changed files with 32 additions and 24 deletions

View File

@ -66,6 +66,7 @@ func Test(t *testing.T) {
runGo("Build", workDir, "go", "build", "./...") runGo("Build", workDir, "go", "build", "./...")
runGo("TestNormal", workDir, "go", "test", "-race", "./...") runGo("TestNormal", workDir, "go", "test", "-race", "./...")
runGo("TestPureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...") runGo("TestPureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...")
runGo("TestReflect", workDir, "go", "test", "-race", "-tags", "protoreflect", "./...")
if v == golangLatest { if v == golangLatest {
runGo("TestProto1Legacy", workDir, "go", "test", "-race", "-tags", "proto1_legacy", "./...") runGo("TestProto1Legacy", workDir, "go", "test", "-race", "-tags", "proto1_legacy", "./...")
runGo("TestProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test") runGo("TestProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test")

View File

@ -25,10 +25,6 @@ type UnmarshalOptions struct {
// If DiscardUnknown is set, unknown fields are ignored. // If DiscardUnknown is set, unknown fields are ignored.
DiscardUnknown bool DiscardUnknown bool
// Reflection forces use of the reflection-based decoder, even for
// messages which implement fast-path deserialization.
Reflection bool
pragma.NoUnkeyedLiterals pragma.NoUnkeyedLiterals
} }
@ -57,9 +53,6 @@ func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
} }
func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error { func (o UnmarshalOptions) unmarshalMessageFast(b []byte, m Message) error {
if o.Reflection {
return errInternalNoFast
}
methods := protoMethods(m) methods := protoMethods(m)
if methods == nil || methods.Unmarshal == nil { if methods == nil || methods.Unmarshal == nil {
return errInternalNoFast return errInternalNoFast

View File

@ -47,10 +47,6 @@ type MarshalOptions struct {
// detail and subject to change. // detail and subject to change.
Deterministic bool Deterministic bool
// Reflection forces use of the reflection-based encoder, even for
// messages which implement fast-path serialization.
Reflection bool
pragma.NoUnkeyedLiterals pragma.NoUnkeyedLiterals
} }
@ -84,9 +80,6 @@ func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
} }
func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error) { func (o MarshalOptions) marshalMessageFast(b []byte, m Message) ([]byte, error) {
if o.Reflection {
return nil, errInternalNoFast
}
methods := protoMethods(m) methods := protoMethods(m)
if methods == nil || if methods == nil ||
methods.MarshalAppend == nil || methods.MarshalAppend == nil ||

View File

@ -7,7 +7,6 @@ package proto
import ( import (
"github.com/golang/protobuf/v2/internal/errors" "github.com/golang/protobuf/v2/internal/errors"
"github.com/golang/protobuf/v2/reflect/protoreflect" "github.com/golang/protobuf/v2/reflect/protoreflect"
"github.com/golang/protobuf/v2/runtime/protoiface"
) )
// Message is the top-level interface that all messages must implement. // Message is the top-level interface that all messages must implement.
@ -15,10 +14,3 @@ type Message = protoreflect.ProtoMessage
// errInternalNoFast indicates that fast-path operations are not available for a message. // errInternalNoFast indicates that fast-path operations are not available for a message.
var errInternalNoFast = errors.New("BUG: internal error (errInternalNoFast)") var errInternalNoFast = errors.New("BUG: internal error (errInternalNoFast)")
func protoMethods(m Message) *protoiface.Methods {
if x, ok := m.(protoiface.Methoder); ok {
return x.XXX_Methods()
}
return nil
}

17
proto/proto_methods.go Normal file
View File

@ -0,0 +1,17 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The protoreflect build tag disables use of fast-path methods.
// +build !protoreflect
package proto
import "github.com/golang/protobuf/v2/runtime/protoiface"
func protoMethods(m Message) *protoiface.Methods {
if x, ok := m.(protoiface.Methoder); ok {
return x.XXX_Methods()
}
return nil
}

14
proto/proto_reflect.go Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The protoreflect build tag disables use of fast-path methods.
// +build protoreflect
package proto
import "github.com/golang/protobuf/v2/runtime/protoiface"
func protoMethods(m Message) *protoiface.Methods {
return nil
}

View File

@ -55,7 +55,6 @@ const (
type MarshalOptions struct { type MarshalOptions struct {
AllowPartial bool AllowPartial bool
Deterministic bool Deterministic bool
Reflection bool
pragma.NoUnkeyedLiterals pragma.NoUnkeyedLiterals
} }
@ -66,7 +65,6 @@ type MarshalOptions struct {
type UnmarshalOptions struct { type UnmarshalOptions struct {
AllowPartial bool AllowPartial bool
DiscardUnknown bool DiscardUnknown bool
Reflection bool
pragma.NoUnkeyedLiterals pragma.NoUnkeyedLiterals
} }