All functionality has been re-written to either wrap v2 directly
(e.g., binary serialization) or written to use v2 protobuf reflection
(e.g., text and json serialization). This is to done to reduce the
technical debt of maintaining the v1 module.

Change-Id: I6749fa58a465df991c8fcf89e8d7077d64a2cfdb
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/213901
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Joe Tsai 2020-01-08 20:52:47 -08:00 коммит произвёл Joe Tsai
Родитель ff0ab7ff11
Коммит cc376d7145
81 изменённых файлов: 6931 добавлений и 17174 удалений

Просмотреть файл

@ -2,64 +2,183 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package descriptor provides functions for obtaining protocol buffer
// descriptors for generated Go types.
// Package descriptor provides functions for obtaining the protocol buffer
// descriptors of generated Go types.
//
// Deprecated: Do not use. The new v2 Message interface provides direct support
// for programmatically interacting with the descriptor information.
// Deprecated: Use the "google.golang.org/protobuf/reflect/protoreflect"
// package instead to obtain an EnumDescriptor or MessageDescriptor in order to
// programatically interact with the protobuf type system.
package descriptor
import (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"sync"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
// extractFile extracts a FileDescriptorProto from a gzip'd buffer.
func extractFile(gz []byte) (*descriptorpb.FileDescriptorProto, error) {
r, err := gzip.NewReader(bytes.NewReader(gz))
if err != nil {
return nil, fmt.Errorf("failed to open gzip reader: %v", err)
}
defer r.Close()
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("failed to uncompress descriptor: %v", err)
}
fd := new(descriptorpb.FileDescriptorProto)
if err := proto.Unmarshal(b, fd); err != nil {
return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err)
}
return fd, nil
}
// Message is a proto.Message with a method to return its descriptor.
//
// Message types generated by the protocol compiler always satisfy
// the Message interface.
// Message is proto.Message with a method to return its descriptor.
// Not every message is guaranteed to implement this interface.
type Message interface {
proto.Message
Descriptor() ([]byte, []int)
}
// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it
// describing the given message.
func ForMessage(msg Message) (fd *descriptorpb.FileDescriptorProto, md *descriptorpb.DescriptorProto) {
gz, path := msg.Descriptor()
fd, err := extractFile(gz)
if err != nil {
panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err))
// ForMessage returns the file descriptor proto containing
// the message and the message descriptor proto for the message itself.
// The returned proto messages must not be mutated.
func ForMessage(m Message) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) {
return MessageDescriptorProtoOf(m)
}
// GeneratedEnum is any enum type generated by protoc-gen-go
// which is a named int32 kind.
type GeneratedEnum interface{}
// GeneratedMessage is any message type generated by protoc-gen-go
// which is a pointer to a named struct kind.
type GeneratedMessage interface{}
type rawDesc struct {
fileDesc []byte
indexes []int
}
var rawDescCache sync.Map // map[protoreflect.Descriptor]*rawDesc
func deriveRawDescriptor(d protoreflect.Descriptor) ([]byte, []int) {
// Fast-path: check whether raw descriptors are already cached.
origDesc := d
if v, ok := rawDescCache.Load(origDesc); ok {
return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes
}
md = fd.MessageType[path[0]]
for _, i := range path[1:] {
// Slow-path: derive the raw descriptor from the v2 descriptor.
// Start with the leaf (a given enum or message declaration) and
// ascend upwards until we hit the parent file descriptor.
var idxs []int
for {
idxs = append(idxs, d.Index())
d = d.Parent()
if d == nil {
// TODO: We could construct a FileDescriptor stub for standalone
// descriptors to satisfy the API.
return nil, nil
}
if _, ok := d.(protoreflect.FileDescriptor); ok {
break
}
}
// Obtain the raw file descriptor.
var raw []byte
switch fd := d.(type) {
case interface{ ProtoLegacyRawDesc() []byte }:
raw = fd.ProtoLegacyRawDesc()
case protoreflect.FileDescriptor:
raw, _ = proto.Marshal(protodesc.ToFileDescriptorProto(fd))
}
file := protoimpl.X.CompressGZIP(raw)
// Reverse the indexes, since we populated it in reverse.
for i, j := 0, len(idxs)-1; i < j; i, j = i+1, j-1 {
idxs[i], idxs[j] = idxs[j], idxs[i]
}
if v, ok := rawDescCache.LoadOrStore(origDesc, &rawDesc{file, idxs}); ok {
return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes
}
return file, idxs
}
// EnumRawDescriptorOf returns the GZIP'd raw file descriptor containing the
// enum and the index path to reach the enum declaration.
// The returned slices must not be mutated.
func EnumRawDescriptorOf(e GeneratedEnum) ([]byte, []int) {
if ev, ok := e.(interface{ EnumDescriptor() ([]byte, []int) }); ok {
return ev.EnumDescriptor()
}
ed := protoimpl.X.EnumTypeOf(e)
return deriveRawDescriptor(ed.Descriptor())
}
// MessageRawDescriptorOf returns the GZIP'd raw file descriptor containing
// the message and the index path to reach the message declaration.
// The returned slices must not be mutated.
func MessageRawDescriptorOf(m GeneratedMessage) ([]byte, []int) {
if mv, ok := m.(interface{ Descriptor() ([]byte, []int) }); ok {
return mv.Descriptor()
}
md := protoimpl.X.MessageTypeOf(m)
return deriveRawDescriptor(md.Descriptor())
}
var fileDescCache sync.Map // map[*byte]*descriptorpb.FileDescriptorProto
func deriveFileDescriptor(rawDesc []byte) *descriptorpb.FileDescriptorProto {
// Fast-path: check whether descriptor protos are already cached.
if v, ok := fileDescCache.Load(&rawDesc[0]); ok {
return v.(*descriptorpb.FileDescriptorProto)
}
// Slow-path: derive the descriptor proto from the GZIP'd message.
zr, err := gzip.NewReader(bytes.NewReader(rawDesc))
if err != nil {
panic(err)
}
b, err := ioutil.ReadAll(zr)
if err != nil {
panic(err)
}
fd := new(descriptorpb.FileDescriptorProto)
if err := proto.Unmarshal(b, fd); err != nil {
panic(err)
}
if v, ok := fileDescCache.LoadOrStore(&rawDesc[0], fd); ok {
return v.(*descriptorpb.FileDescriptorProto)
}
return fd
}
// EnumDescriptorProtoOf returns the file descriptor proto containing
// the enum and the enum descriptor proto for the enum itself.
// The returned proto messages must not be mutated.
func EnumDescriptorProtoOf(e GeneratedEnum) (*descriptorpb.FileDescriptorProto, *descriptorpb.EnumDescriptorProto) {
rawDesc, idxs := EnumRawDescriptorOf(e)
if rawDesc == nil || idxs == nil {
return nil, nil
}
fd := deriveFileDescriptor(rawDesc)
if len(idxs) == 1 {
return fd, fd.EnumType[idxs[0]]
}
md := fd.MessageType[idxs[0]]
for _, i := range idxs[1 : len(idxs)-1] {
md = md.NestedType[i]
}
ed := md.EnumType[idxs[len(idxs)-1]]
return fd, ed
}
// MessageDescriptorProtoOf returns the file descriptor proto containing
// the message and the message descriptor proto for the message itself.
// The returned proto messages must not be mutated.
func MessageDescriptorProtoOf(m GeneratedMessage) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) {
rawDesc, idxs := MessageRawDescriptorOf(m)
if rawDesc == nil || idxs == nil {
return nil, nil
}
fd := deriveFileDescriptor(rawDesc)
md := fd.MessageType[idxs[0]]
for _, i := range idxs[1:] {
md = md.NestedType[i]
}
return fd, md

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright 2020 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.
package descriptor
import (
"testing"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/reflect/protoreflect"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
func TestEnumDescriptorOf(t *testing.T) {
tests := []struct {
enum protoreflect.Enum
idxs []int
name string
}{{
enum: descpb.FieldDescriptorProto_Type(0),
idxs: []int{
new(descpb.FieldDescriptorProto).ProtoReflect().Descriptor().Index(),
new(descpb.FieldDescriptorProto_Type).Descriptor().Index(),
},
name: "Type",
}, {
enum: descpb.FieldOptions_CType(0),
idxs: []int{
new(descpb.FieldOptions).ProtoReflect().Descriptor().Index(),
new(descpb.FieldOptions_CType).Descriptor().Index(),
},
name: "CType",
}}
for _, tt := range tests {
e := struct{ protoreflect.Enum }{tt.enum} // v2-only enum
_, idxs := EnumRawDescriptorOf(e)
if diff := cmp.Diff(tt.idxs, idxs); diff != "" {
t.Errorf("path index mismatch (-want +got):\n%v", diff)
}
_, ed := EnumDescriptorProtoOf(e)
if ed.GetName() != tt.name {
t.Errorf("mismatching enum name: got %v, want %v", ed.GetName(), tt.name)
}
}
}
func TestMessageDescriptorOf(t *testing.T) {
tests := []struct {
message protoreflect.ProtoMessage
idxs []int
name string
}{{
message: (*descpb.SourceCodeInfo_Location)(nil),
idxs: []int{
new(descpb.SourceCodeInfo).ProtoReflect().Descriptor().Index(),
new(descpb.SourceCodeInfo_Location).ProtoReflect().Descriptor().Index(),
},
name: "Location",
}, {
message: (*descpb.FileDescriptorProto)(nil),
idxs: []int{
new(descpb.FileDescriptorProto).ProtoReflect().Descriptor().Index(),
},
name: "FileDescriptorProto",
}}
for _, tt := range tests {
m := struct{ protoreflect.ProtoMessage }{tt.message} // v2-only message
_, idxs := MessageRawDescriptorOf(m)
if diff := cmp.Diff(tt.idxs, idxs); diff != "" {
t.Errorf("path index mismatch (-want +got):\n%v", diff)
}
_, md := MessageDescriptorProtoOf(m)
if md.GetName() != tt.name {
t.Errorf("mismatching message name: got %v, want %v", md.GetName(), tt.name)
}
}
}

4
go.mod
Просмотреть файл

@ -3,6 +3,6 @@ module github.com/golang/protobuf
go 1.9
require (
github.com/google/go-cmp v0.3.1 // indirect
google.golang.org/protobuf v0.0.0-20191108002925-e9187326c3ff
github.com/google/go-cmp v0.3.1
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd
)

33
go.sum
Просмотреть файл

@ -1,34 +1,5 @@
github.com/golang/protobuf v1.2.1-0.20190514181236-7800af189d76/go.mod h1:Zfz6qcDoDBESdv6JsKsGpgNHnkvwJAJwcA9eL+mOkgc=
github.com/golang/protobuf v1.2.1-0.20190515194842-7574ba03306e/go.mod h1:GjgUz9uwrRQmdPBBrFqiVbojAmlpy6ryM6DCzC+20rE=
github.com/golang/protobuf v1.2.1-0.20190516201927-a2cd3ac1b343/go.mod h1:PScGDF2x230A126tLt9Ol9RjhXzbiPJrt/CogooD2mE=
github.com/golang/protobuf v1.2.1-0.20190516215712-ae2eaafab405/go.mod h1:UmP8hhPKR5WWIjbT9v0JEVT+U0DBSjbW8KaZVeyFfRE=
github.com/golang/protobuf v1.2.1-0.20190523175523-a1331f0b4ab4/go.mod h1:G+fNMoyvKWZDB7PCDHF+dXbH9OeE3+JoozCd9V7i66U=
github.com/golang/protobuf v1.2.1-0.20190605195750-76c9e09470ba/go.mod h1:S1YIJXvYHGRCG2UmZsOcElkAYfvZLg2sDRr9+Xu8JXU=
github.com/golang/protobuf v1.2.1-0.20190617175902-f94016f5239f/go.mod h1:G+HpKX7pYZAVkElkAWZkr08MToW6pTp/vs+E9osFfbg=
github.com/golang/protobuf v1.2.1-0.20190620192300-1ee46dfd80dd/go.mod h1:+CMAsi9jpYf/wAltLUKlg++CWXqxCJyD8iLDbQONsJs=
github.com/golang/protobuf v1.2.1-0.20190806214225-7037721e6de0/go.mod h1:tDQPRlaHYu9yt1wPgdx85inRiLvUCuJZXsYjC0mwc1c=
github.com/golang/protobuf v1.2.1-0.20190820204156-2da1b93405dd/go.mod h1:x87I3ou7ehf/yR6iQ88MkyDogdxXN04TELJ7HVy7V7I=
github.com/golang/protobuf v1.2.1-0.20190820213554-ae1d65bc5435/go.mod h1:k7dGkiTZ3rjVDhKSpGt+x1zDzAePJk4jdhoBwIkQgBo=
github.com/golang/protobuf v1.2.1-0.20191004062209-62f67f1ea9df/go.mod h1:o4el5ABfDjqFlwwvAq2OIgAPeNXQYUkhtrjNPXy6T6I=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
google.golang.org/protobuf v0.0.0-20190514172829-e89e6244e0e8/go.mod h1:791zQGC15vDqjpmPRn1uGPu5oHy/Jzw/Q1n5JsgIIcY=
google.golang.org/protobuf v0.0.0-20190514231807-cdb777356907/go.mod h1:HeRLsKXv4+wE27dOIGwnqcOgq6a1O/GJ7mGhiEPnBrU=
google.golang.org/protobuf v0.0.0-20190516201745-40b83d67fc75/go.mod h1:jf+u8AHuKtkib+0J4/bQXPNzCmT3V9a02hVzYKtatuw=
google.golang.org/protobuf v0.0.0-20190516215540-a95b29fbf623/go.mod h1:cWWmz5lsCWIcqGLROrKq5Lu231IJw2PzqOZ8cgspbfY=
google.golang.org/protobuf v0.0.0-20190522194032-21ade498bd69/go.mod h1:cJytyYi/6qdwy/+gD49hmgHcwD7zhWxE/1KPEslaZ3M=
google.golang.org/protobuf v0.0.0-20190605195314-89d49632e5cf/go.mod h1:Btug4TBaP5wNYcb2zGKDTS7WMcaPPLuqEAKfEAZWYbo=
google.golang.org/protobuf v0.0.0-20190617175724-bd7b7a9e0c26/go.mod h1:+FOB8T5/Yw4ywwdyeun9/KlDeuwFYBkNQ+kVuwj9C94=
google.golang.org/protobuf v0.0.0-20190620020611-d888139e7b59/go.mod h1:of3pt14Y+dOxz2tBOHXEoapPpKFC15/0zWhPAddkfsU=
google.golang.org/protobuf v0.0.0-20190717230113-f647c82cc3c7 h1:U6U+Hb+UKNGJB0eMAjUGk0wTmy73kduTIvdsEgA4Gf8=
google.golang.org/protobuf v0.0.0-20190717230113-f647c82cc3c7/go.mod h1:yGm7aNHn9Bp1NIvj6+CVUkcJshu+Usshfd3A+YxEuI8=
google.golang.org/protobuf v0.0.0-20190820203659-c0f8c0a24ece h1:AFYGmds8FWBGNw0zddlFiGtDvkVFSnQ7J2bAdH4X9Xk=
google.golang.org/protobuf v0.0.0-20190820203659-c0f8c0a24ece/go.mod h1:tRqhEyKwbKqwt5CQZAuOtj09RfhLNklDOhndhYA9blU=
google.golang.org/protobuf v0.0.0-20190820213257-f1e905b04207 h1:ulV4hvtdAg7XsymkxyxHtKYxQoSq88XU1bmtCELxG38=
google.golang.org/protobuf v0.0.0-20190820213257-f1e905b04207/go.mod h1:UJqt2ZERO8/qk5A9t8Ujq6OJ+MNvOQpg9X4RKyYz9Ho=
google.golang.org/protobuf v0.0.0-20190828183429-79bfdbe45be2 h1:g52BKWg08C9Z3iSV/mBCfoP+ObYXKCgdXF+p1EB9zD0=
google.golang.org/protobuf v0.0.0-20190828183429-79bfdbe45be2/go.mod h1:fYMzYhnMXLj/kGDPzNOptS3IFFlQjWTlu2j3ZPET2lw=
google.golang.org/protobuf v0.0.0-20191108002925-e9187326c3ff h1:owlmxbzMXWq78QqeFT2Xj1ySspP/ot+aFzxHoz79YLQ=
google.golang.org/protobuf v0.0.0-20191108002925-e9187326c3ff/go.mod h1:qKrTvhhUFcTIUF6KuejTfRdHXKeBPoa4mtynR6usTss=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd h1:zSMqFwpTkfj+1nNFgmgu4B+Qv5Kpf4jpd11lCmHKuwQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=

Просмотреть файл

@ -1,73 +0,0 @@
// 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.
package proto
// TODO: This file exists to provide the illusion to other source files that
// they live within the real proto package by providing functions and types
// that they would otherwise be able to call directly.
import (
"fmt"
"reflect"
"google.golang.org/protobuf/runtime/protoiface"
"google.golang.org/protobuf/runtime/protoimpl"
)
type (
Message = protoiface.MessageV1
ExtensionDesc = protoimpl.ExtensionInfo
)
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
// Marshal reports this when a required field is not initialized.
// Unmarshal reports this when a required field is missing from the input data.
type RequiredNotSetError struct{ field string }
func (e *RequiredNotSetError) Error() string {
if e.field == "" {
return fmt.Sprintf("proto: required field not set")
}
return fmt.Sprintf("proto: required field %q not set", e.field)
}
func (e *RequiredNotSetError) RequiredNotSet() bool {
return true
}
type errorMask uint8
const (
_ errorMask = (1 << iota) / 2
errInvalidUTF8
errRequiredNotSet
)
type errorsList = []error
var errorsListType = reflect.TypeOf(errorsList{})
// nonFatalErrors returns an errorMask identifying V2 non-fatal errors.
func nonFatalErrors(err error) errorMask {
verr := reflect.ValueOf(err)
if !verr.IsValid() {
return 0
}
if !verr.Type().AssignableTo(errorsListType) {
return 0
}
errs := verr.Convert(errorsListType).Interface().(errorsList)
var ret errorMask
for _, e := range errs {
switch e.(type) {
case interface{ RequiredNotSet() bool }:
ret |= errRequiredNotSet
case interface{ InvalidUTF8() bool }:
ret |= errInvalidUTF8
}
}
return ret
}

Просмотреть файл

@ -1,63 +0,0 @@
// 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.
package proto
import (
"errors"
"testing"
)
type testErrorList []error
func (e testErrorList) Error() string {
return "testErrorList"
}
type invalidUTF8Error struct{}
func (e invalidUTF8Error) Error() string { return "" }
func (e invalidUTF8Error) InvalidUTF8() bool { return true }
type requiredNotSetError struct{}
func (e requiredNotSetError) Error() string { return "" }
func (e requiredNotSetError) RequiredNotSet() bool { return true }
func TestNonFatalErrors(t *testing.T) {
tests := []struct {
input error
want errorMask
}{{
input: errors.New("not one of them"),
}, {
input: testErrorList{},
}, {
input: testErrorList{
invalidUTF8Error{},
},
want: errInvalidUTF8,
}, {
input: testErrorList{
requiredNotSetError{},
},
want: errRequiredNotSet,
}, {
input: testErrorList{
invalidUTF8Error{},
requiredNotSetError{},
},
want: errInvalidUTF8 | errRequiredNotSet,
}}
for _, tc := range tests {
tc := tc
t.Run("", func(t *testing.T) {
got := nonFatalErrors(tc.input)
if got != tc.want {
t.Errorf("got %v, want %v", got, tc.want)
}
})
}
}

Просмотреть файл

@ -1,63 +0,0 @@
// 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.
package proto
import (
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
)
// SetDefaults sets unset protocol buffer fields to their default values.
// It only modifies fields that are both unset and have defined defaults.
// It recursively sets default values in any non-nil sub-messages.
// It does not descend into extension fields that are sub-messages.
func SetDefaults(m Message) {
setDefaults(protoimpl.X.MessageOf(m))
}
func setDefaults(m pref.Message) {
fieldDescs := m.Descriptor().Fields()
for i := 0; i < fieldDescs.Len(); i++ {
fd := fieldDescs.Get(i)
if !m.Has(fd) {
if fd.HasDefault() {
v := fd.Default()
if fd.Kind() == pref.BytesKind {
v = pref.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes
}
m.Set(fd, v)
}
continue
}
switch {
// Handle singular message.
case fd.Cardinality() != pref.Repeated:
if k := fd.Kind(); k == pref.MessageKind || k == pref.GroupKind {
setDefaults(m.Get(fd).Message())
}
// Handle list of messages.
case !fd.IsMap():
if k := fd.Kind(); k == pref.MessageKind || k == pref.GroupKind {
ls := m.Get(fd).List()
for i := 0; i < ls.Len(); i++ {
setDefaults(ls.Get(i).Message())
}
}
// Handle map of messages.
default:
k := fd.Message().Fields().ByNumber(2).Kind()
if k == pref.MessageKind || k == pref.GroupKind {
ms := m.Get(fd).Map()
ms.Range(func(_ pref.MapKey, v pref.Value) bool {
setDefaults(v.Message())
return true
})
}
}
}
// NOTE: Historically, this function has never set the defaults for
// extension fields, nor recursively visited sub-messages of such fields.
}

Просмотреть файл

@ -1,75 +0,0 @@
// 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.
package proto
import (
"github.com/golang/protobuf/internal/wire"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
)
// DiscardUnknown recursively discards all unknown fields from this message
// and all embedded messages.
//
// When unmarshaling a message with unrecognized fields, the tags and values
// of such fields are preserved in the Message. This allows a later call to
// marshal to be able to produce a message that continues to have those
// unrecognized fields. To avoid this, DiscardUnknown is used to
// explicitly clear the unknown fields after unmarshaling.
//
// For proto2 messages, the unknown fields of message extensions are only
// discarded from messages that have been accessed via GetExtension.
func DiscardUnknown(m Message) {
if m == nil {
return
}
discardUnknown(protoimpl.X.MessageOf(m))
}
func discardUnknown(m pref.Message) {
m.Range(func(fd pref.FieldDescriptor, val pref.Value) bool {
switch {
// Handle singular message.
case fd.Cardinality() != pref.Repeated:
if fd.Message() != nil {
discardUnknown(m.Get(fd).Message())
}
// Handle list of messages.
case fd.IsList():
if fd.Message() != nil {
ls := m.Get(fd).List()
for i := 0; i < ls.Len(); i++ {
discardUnknown(ls.Get(i).Message())
}
}
// Handle map of messages.
case fd.IsMap():
if fd.MapValue().Message() != nil {
ms := m.Get(fd).Map()
ms.Range(func(_ pref.MapKey, v pref.Value) bool {
discardUnknown(v.Message())
return true
})
}
}
return true
})
// Discard unknown fields.
var bo pref.RawFields
extRanges := m.Descriptor().ExtensionRanges()
for bi := m.GetUnknown(); len(bi) > 0; {
// NOTE: Historically, this function did not discard unknown fields
// that were within the extension field ranges.
num, _, n := wire.ConsumeField(bi)
if extRanges.Has(num) {
bo = append(bo, bi[:n]...)
}
bi = bi[n:]
}
if bi := m.GetUnknown(); len(bi) != len(bo) {
m.SetUnknown(bo)
}
}

Просмотреть файл

@ -1,321 +0,0 @@
// Copyright 2010 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.
package proto
import (
"fmt"
"reflect"
"strconv"
"strings"
"sync"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/runtime/protoimpl"
)
// Constants that identify the encoding of a value on the wire.
const (
WireVarint = 0
WireFixed32 = 5
WireFixed64 = 1
WireBytes = 2
WireStartGroup = 3
WireEndGroup = 4
)
// StructProperties represents protocol buffer type information for a
// generated protobuf message in the open-struct API.
//
// Deprecated: Do not use.
type StructProperties struct {
// Prop are the properties for each field.
//
// Fields belonging to a oneof are stored in OneofTypes instead, with a
// single Properties representing the parent oneof held here.
//
// The order of Prop matches the order of fields in the Go struct.
// Struct fields that are not related to protobufs have a "XXX_" prefix
// in the Properties.Name and must be ignored by the user.
Prop []*Properties
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the protobuf field name.
OneofTypes map[string]*OneofProperties
}
// Properties represents the type information for a protobuf message field.
//
// Deprecated: Do not use.
type Properties struct {
// Name is a placeholder name with little meaningful semantic value.
// Fields with an "XXX_" prefix must be ignored.
Name string
// OrigName is the protobuf field name or oneof name.
OrigName string
// JSONName is the JSON name for the protobuf field.
JSONName string
// Enum is a placeholder name for enums.
// For historical reasons, this is neither the Go name for the enum,
// nor the protobuf name for the enum.
Enum string // Deprecated: Do not use.
// Wire is a string representation of the wire type.
Wire string
// WireType is the protobuf wire type for the field.
WireType int
// Tag is the protobuf field number.
Tag int
// Required reports whether this is a required field.
Required bool
// Optional reports whether this is a optional field.
Optional bool
// Repeated reports whether this is a repeated field.
Repeated bool
// Packed reports whether this is a packed repeated field of scalars.
Packed bool
// Proto3 reports whether this field operates under the proto3 syntax.
Proto3 bool
// Oneof reports whether this field belongs within a oneof.
Oneof bool
// Default is the default value in string form.
Default string
// HasDefault reports whether the field has a default value.
HasDefault bool
// MapKeyProp is the properties for the key field for a map field.
MapKeyProp *Properties
// MapValProp is the properties for the value field for a map field.
MapValProp *Properties
}
// OneofProperties represents the type information for a protobuf oneof.
//
// Deprecated: Do not use.
type OneofProperties struct {
// Type is a pointer to the generated wrapper type for the field value.
// This is nil for messages that are not in the open-struct API.
Type reflect.Type
// Field is the index into StructProperties.Prop for the containing oneof.
Field int
// Prop is the properties for the field.
Prop *Properties
}
// String formats the properties in the protobuf struct field tag style.
func (p *Properties) String() string {
s := p.Wire
s += "," + strconv.Itoa(p.Tag)
if p.Required {
s += ",req"
}
if p.Optional {
s += ",opt"
}
if p.Repeated {
s += ",rep"
}
if p.Packed {
s += ",packed"
}
s += ",name=" + p.OrigName
if p.JSONName != "" {
s += ",json=" + p.JSONName
}
if p.Proto3 {
s += ",proto3"
}
if p.Oneof {
s += ",oneof"
}
if len(p.Enum) > 0 {
s += ",enum=" + p.Enum
}
if p.HasDefault {
s += ",def=" + p.Default
}
return s
}
// Parse populates p by parsing a string in the protobuf struct field tag style.
func (p *Properties) Parse(tag string) {
// For example: "bytes,49,opt,name=foo,def=hello!"
for len(tag) > 0 {
i := strings.IndexByte(tag, ',')
if i < 0 {
i = len(tag)
}
switch s := tag[:i]; {
case strings.HasPrefix(s, "name="):
p.OrigName = s[len("name="):]
case strings.HasPrefix(s, "json="):
p.JSONName = s[len("json="):]
case strings.HasPrefix(s, "enum="):
p.Enum = s[len("enum="):]
case strings.Trim(s, "0123456789") == "":
n, _ := strconv.ParseUint(s, 10, 32)
p.Tag = int(n)
case s == "opt":
p.Optional = true
case s == "req":
p.Required = true
case s == "rep":
p.Repeated = true
case s == "varint" || s == "zigzag32" || s == "zigzag64":
p.Wire = s
p.WireType = WireVarint
case s == "fixed32":
p.Wire = s
p.WireType = WireFixed32
case s == "fixed64":
p.Wire = s
p.WireType = WireFixed64
case s == "bytes":
p.Wire = s
p.WireType = WireBytes
case s == "group":
p.Wire = s
p.WireType = WireStartGroup
case s == "packed":
p.Packed = true
case s == "proto3":
p.Proto3 = true
case s == "oneof":
p.Oneof = true
case strings.HasPrefix(s, "def="):
// The default tag is special in that everything afterwards is the
// default regardless of the presence of commas.
p.HasDefault = true
p.Default, i = tag[len("def="):], len(tag)
}
tag = strings.TrimPrefix(tag[i:], ",")
}
}
// Init populates the properties from a protocol buffer struct tag.
//
// Deprecated: Do not use.
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.init(typ, name, tag, f)
}
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.Name = name
p.OrigName = name
if tag == "" {
return
}
p.Parse(tag)
if typ != nil && typ.Kind() == reflect.Map {
p.MapKeyProp = new(Properties)
p.MapKeyProp.init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
p.MapValProp = new(Properties)
p.MapValProp.init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
}
}
var propertiesCache sync.Map // map[reflect.Type]*StructProperties
// GetProperties returns the list of properties for the type represented by t,
// which must be a generated protocol buffer message in the open-struct API,
// where protobuf message fields are represented by exported Go struct fields.
//
// Deprecated: Use v2 protobuf reflection instead.
func GetProperties(t reflect.Type) *StructProperties {
if p, ok := propertiesCache.Load(t); ok {
return p.(*StructProperties)
}
p, _ := propertiesCache.LoadOrStore(t, newProperties(t))
return p.(*StructProperties)
}
func newProperties(t reflect.Type) *StructProperties {
if t.Kind() != reflect.Struct {
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
}
var foundField bool
prop := new(StructProperties)
// Construct a list of properties for each field in the struct.
for i := 0; i < t.NumField(); i++ {
p := new(Properties)
f := t.Field(i)
tagField := f.Tag.Get("protobuf")
p.init(f.Type, f.Name, tagField, &f)
foundField = foundField || p.Tag > 0
tagOneof := f.Tag.Get("protobuf_oneof")
if tagOneof != "" {
p.OrigName = tagOneof
}
// Rename unexported struct fields with the "XXX_" prefix since so much
// user code simply checks for this to exclude unrelated fields.
if f.PkgPath != "" {
p.Name = "XXX_" + p.Name
}
prop.Prop = append(prop.Prop, p)
}
// Construct a mapping of oneof field names to properties.
var oneofWrappers []interface{}
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
}
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
}
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoV2.Message); ok {
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
oneofWrappers = m.ProtoMessageInfo().OneofWrappers
}
}
if len(oneofWrappers) > 0 {
prop.OneofTypes = make(map[string]*OneofProperties)
for _, wrapper := range oneofWrappers {
p := &OneofProperties{
Type: reflect.ValueOf(wrapper).Type(), // *T
Prop: new(Properties),
}
f := p.Type.Elem().Field(0)
p.Prop.Name = f.Name
p.Prop.Parse(f.Tag.Get("protobuf"))
foundField = foundField || p.Prop.Tag > 0
// Determine the struct field that contains this oneof.
// Each wrapper is assignable to exactly one parent field.
var foundOneof bool
for i := 0; i < t.NumField() && !foundOneof; i++ {
if p.Type.AssignableTo(t.Field(i).Type) {
p.Field = i
foundOneof = true
}
}
if !foundOneof {
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
}
prop.OneofTypes[p.Prop.OrigName] = p
}
}
// If we found no fields, it is possible that the struct uses a
// generated API that is not an open-struct layout.
if !foundField {
// Check with protobuf reflection to make sure this isn't
// an empty protobuf message.
mt := protoimpl.X.MessageDescriptorOf(reflect.New(t).Interface())
if mt.Fields().Len() > 0 {
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
}
}
return prop
}
func (sp *StructProperties) Len() int { return len(sp.Prop) }
func (sp *StructProperties) Less(i, j int) bool { return false }
func (sp *StructProperties) Swap(i, j int) { return }

Просмотреть файл

@ -1,363 +0,0 @@
// 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.
package proto
import (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"os"
"reflect"
"runtime"
"strings"
"sync"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protodesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
"google.golang.org/protobuf/types/descriptorpb"
)
// filePath is the path to the proto source file.
type filePath = string // e.g., "google/protobuf/descriptor.proto"
// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
type fileDescGZIP = []byte
var fileCache sync.Map // map[filePath]fileDescGZIP
// RegisterFile is called from generated code and registers the compressed
// FileDescriptorProto with the file path for a proto source file.
//
// Deprecated: Use protoregistry.GlobalFiles.Register instead.
func RegisterFile(s filePath, d fileDescGZIP) {
// Decompress the descriptor.
zr, err := gzip.NewReader(bytes.NewReader(d))
if err != nil {
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
}
b, err := ioutil.ReadAll(zr)
if err != nil {
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
}
// Parse the raw descriptor proto.
var pb descriptorpb.FileDescriptorProto
if err := protoV2.Unmarshal(b, &pb); err != nil {
panic(fmt.Sprintf("proto: unmarshal failure: %v", err))
}
// Some old descriptors don't include the filename.
if pb.Name == nil {
pb.Name = &s
}
// Convert the raw descriptor to a structured file descriptor.
fd, err := protodesc.NewFile(&pb, nil)
if err != nil {
// TODO: Ignore errors due to placeholders.
panic(fmt.Sprintf("proto: descriptor parsing failure: %v", err))
}
// Register the descriptor in the v2 registry and cache the result locally.
if err := protoregistry.GlobalFiles.RegisterFile(fd); err != nil {
printWarning(err)
return
}
fileCache.Store(s, b)
}
// FileDescriptor returns the compressed FileDescriptorProto given the file path
// for a proto source file. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalFiles.RangeFilesByPath instead.
func FileDescriptor(s filePath) (d fileDescGZIP) {
if d, ok := fileCache.Load(s); ok {
return d.(fileDescGZIP)
}
// Find the descriptor in the v2 registry.
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
pb := protodesc.ToFileDescriptorProto(fd)
b, err := protoV2.Marshal(pb)
if err != nil {
panic(fmt.Sprintf("proto: marshal failure: %v", err))
}
bb := new(bytes.Buffer)
zw := gzip.NewWriter(bb)
if _, err := zw.Write(b); err != nil {
panic(fmt.Sprintf("proto: compression failure: %v", err))
}
if err := zw.Close(); err != nil {
panic(fmt.Sprintf("proto: compression failure: %v", err))
}
d = bb.Bytes()
}
// Locally cache the raw descriptor form for the file.
if len(d) > 0 {
fileCache.Store(s, d)
}
return d
}
// enumName is the name of an enum. For historical reasons, the enum name is
// neither the full Go name nor the full protobuf name of the enum.
// The name is the dot-separated combination of just the proto package that the
// enum is declared within followed by the Go type name of the generated enum.
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"
// enumsByName maps enum values by name to their numeric counterpart.
type enumsByName = map[string]int32
// enumsByNumber maps enum values by number to their name counterpart.
type enumsByNumber = map[int32]string
var enumCache sync.Map // map[enumName]enumsByName
// RegisterEnum is called from the generated code and registers the mapping of
// enum value names to enum numbers for the enum identified by s.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
if _, ok := enumCache.Load(s); ok {
panic("proto: duplicate enum registered: " + s)
}
enumCache.Store(s, m)
// This does not forward registration to the v2 registry since this API
// lacks sufficient information to construct a complete v2 enum descriptor.
}
// EnumValueMap returns the mapping from enum value names to enum numbers for
// the enum of the given name. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
func EnumValueMap(s enumName) (m enumsByName) {
v, ok := enumCache.Load(s)
if ok {
return v.(enumsByName)
}
// Construct the mapping from a v2 enum descriptor.
var protoPkg pref.FullName
if i := strings.LastIndexByte(s, '.'); i >= 0 {
protoPkg = pref.FullName(s[:i])
}
protoregistry.GlobalFiles.RangeFilesByPackage(pref.FullName(protoPkg), func(fd pref.FileDescriptor) bool {
return walkEnums(fd, func(ed pref.EnumDescriptor) bool {
if s == hybridEnumName(ed) {
m = make(enumsByName)
evs := ed.Values()
for i := evs.Len() - 1; i >= 0; i-- {
ev := evs.Get(i)
m[string(ev.Name())] = int32(ev.Number())
}
return false
}
return true
})
})
if m != nil {
enumCache.Store(s, m)
}
return m
}
// walkEnums recursively walks all enums declared in d.
func walkEnums(d interface {
Enums() pref.EnumDescriptors
Messages() pref.MessageDescriptors
}, f func(pref.EnumDescriptor) bool) bool {
cont := true
eds := d.Enums()
for i := eds.Len() - 1; cont && i >= 0; i-- {
cont = cont && f(eds.Get(i))
}
mds := d.Messages()
for i := mds.Len() - 1; cont && i >= 0; i-- {
cont = cont && walkEnums(mds.Get(i), f)
}
return cont
}
// hybridEnumName returns the legacy enum identifier.
func hybridEnumName(ed pref.EnumDescriptor) enumName {
var protoPkg string
if fd := ed.ParentFile(); fd != nil {
protoPkg = string(fd.Package())
}
if protoPkg == "" {
return camelCase(string(ed.FullName()))
}
return protoPkg + "." + camelCase(strings.TrimPrefix(string(ed.FullName()), protoPkg+"."))
}
// camelCase is a copy of the v2 protogen.camelCase function.
func camelCase(s string) string {
isASCIILower := func(c byte) bool {
return 'a' <= c && c <= 'z'
}
isASCIIDigit := func(c byte) bool {
return '0' <= c && c <= '9'
}
var b []byte
for i := 0; i < len(s); i++ {
c := s[i]
switch {
case c == '.' && i+1 < len(s) && isASCIILower(s[i+1]):
continue
case c == '.':
b = append(b, '_')
case c == '_' && (i == 0 || s[i-1] == '.'):
b = append(b, 'X')
case c == '_' && i+1 < len(s) && isASCIILower(s[i+1]):
continue
case isASCIIDigit(c):
b = append(b, c)
default:
if isASCIILower(c) {
c -= 'a' - 'A'
}
b = append(b, c)
for ; i+1 < len(s) && isASCIILower(s[i+1]); i++ {
b = append(b, s[i+1])
}
}
}
return string(b)
}
// messageName is the full name of protobuf message.
type messageName = string
var messageTypeCache sync.Map // map[messageName]reflect.Type
// RegisterType is called from generated code and register the message Go type
// for a message of the given name.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterType(m Message, s messageName) {
mt := protoimpl.X.MessageTypeOf(m)
if s != messageName(mt.Descriptor().FullName()) {
panic(fmt.Sprintf("proto: inconsistent message name: got %v, want %v", s, mt.Descriptor().FullName()))
}
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
printWarning(err)
return
}
messageTypeCache.Store(s, reflect.TypeOf(m))
}
// RegisterMapType is called from generated code and registers the Go map type
// for a protobuf message representing a map entry.
//
// Deprecated: Do not use.
func RegisterMapType(m interface{}, s messageName) {
t := reflect.TypeOf(m)
if t.Kind() != reflect.Map {
panic(fmt.Sprintf("invalid map kind: %v", t))
}
if _, ok := messageTypeCache.Load(s); ok {
printWarning(fmt.Errorf("proto: duplicate proto message registered: %s", s))
return
}
messageTypeCache.Store(s, t)
}
// MessageType returns the message type for a named message.
// It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
func MessageType(s messageName) reflect.Type {
if t, ok := messageTypeCache.Load(s); ok {
return t.(reflect.Type)
}
// Derive the message type from the v2 registry.
var t reflect.Type
mt, _ := protoregistry.GlobalTypes.FindMessageByName(pref.FullName(s))
if mt != nil {
t = reflect.TypeOf(mt.Zero().Interface())
}
// TODO: Support retrieving Go map types for map entry messages?
if t != nil {
messageTypeCache.Store(s, t)
}
return t
}
// MessageName returns the full protobuf name for the given message type.
//
// Deprecated: Use pref.MessageDescriptor.FullName instead.
func MessageName(m Message) messageName {
if m, ok := m.(interface {
XXX_MessageName() messageName
}); ok {
return m.XXX_MessageName()
}
return messageName(protoimpl.X.MessageDescriptorOf(m).FullName())
}
// RegisterExtension is called from the generated code and registers
// the extension descriptor.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterExtension(d *ExtensionDesc) {
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
panic(err)
}
}
type extensionsByNumber = map[int32]*ExtensionDesc
var extensionCache sync.Map // map[messageName]extensionsByNumber
// RegisteredExtensions returns a map of the registered extensions for the
// provided protobuf message, indexed by the extension field number.
//
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
func RegisteredExtensions(m Message) extensionsByNumber {
s := MessageName(m)
if xs, ok := extensionCache.Load(s); ok {
return xs.(extensionsByNumber)
}
var xs extensionsByNumber
protoregistry.GlobalTypes.RangeExtensionsByMessage(pref.FullName(s), func(xt pref.ExtensionType) bool {
if xs == nil {
xs = make(extensionsByNumber)
}
xs[int32(xt.TypeDescriptor().Number())] = protoimpl.X.ExtensionDescFromType(xt)
return true
})
if xs == nil {
return nil
}
if xs, ok := extensionCache.LoadOrStore(s, xs); ok {
return xs.(extensionsByNumber)
}
return xs
}
// printWarning prints a warning to os.Stderr regarding a registration conflict.
func printWarning(err error) {
// TODO: Provide a link in the warning to a page that explains
// what the user should do instead?
b := make([]byte, 0, 1<<12)
b = append(b, "==================\n"...)
b = append(b, "WARNING: "+err.Error()+"\n"...)
b = append(b, "A future release of proto will panic on registration conflicts.\n\n"...)
b = b[:len(b)+runtime.Stack(b[len(b):cap(b)], false)]
b = append(b, "==================\n"...)
os.Stderr.Write(b)
}

Просмотреть файл

@ -1,117 +0,0 @@
// 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.
package proto
// Functions for writing the text protocol buffer format.
import (
"bytes"
"encoding"
"io"
"reflect"
"google.golang.org/protobuf/encoding/prototext"
preg "google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
// TextMarshaler is a configurable text format marshaler.
type TextMarshaler struct {
Compact bool // use compact text format in one line without the trailing newline character
ExpandAny bool // expand google.protobuf.Any messages of known types
}
// Marshal writes a given protocol buffer in text format.
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
val := reflect.ValueOf(pb)
// V1 supports passing in nil interface or pointer and outputs <nil>, while
// V2 will panic on nil interface and outputs nothing for nil pointer.
if pb == nil || val.IsNil() {
w.Write([]byte("<nil>"))
return nil
}
// V1-specific override in marshaling.
if etm, ok := pb.(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
return err
}
if _, err = w.Write(text); err != nil {
return err
}
return nil
}
var ind string
if !tm.Compact {
ind = " "
}
mo := prototext.MarshalOptions{
AllowPartial: true,
EmitUnknown: true,
Indent: ind,
}
if !tm.ExpandAny {
mo.Resolver = emptyResolver
}
b, err := mo.Marshal(protoimpl.X.MessageOf(pb).Interface())
mask := nonFatalErrors(err)
// V1 does not return invalid UTF-8 error.
if err != nil && mask&errInvalidUTF8 == 0 {
return err
}
if _, err := w.Write(b); err != nil {
return err
}
return nil
}
// Text is the same as Marshal, but returns the string directly.
func (tm *TextMarshaler) Text(pb Message) string {
var buf bytes.Buffer
tm.Marshal(&buf, pb)
return buf.String()
}
var (
emptyResolver = &preg.Types{}
defaultTextMarshaler = TextMarshaler{}
compactTextMarshaler = TextMarshaler{Compact: true}
)
// MarshalText writes a given protocol buffer in text format.
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
// MarshalTextString is the same as MarshalText, but returns the string directly.
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
// CompactText writes a given protocol buffer in compact text format (one line).
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
// CompactTextString is the same as CompactText, but returns the string directly.
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
// UnmarshalText reads a protocol buffer in text format. UnmarshalText resets pb
// before starting to unmarshal, so any existing data in pb is always removed.
// If a required field is not set and no other error occurs, UnmarshalText
// returns *RequiredNotSetError.
func UnmarshalText(s string, m Message) error {
if um, ok := m.(encoding.TextUnmarshaler); ok {
return um.UnmarshalText([]byte(s))
}
err := prototext.Unmarshal([]byte(s), protoimpl.X.MessageOf(m).Interface())
// Return RequiredNotSetError for required not set errors and ignore invalid
// UTF-8 errors.
mask := nonFatalErrors(err)
if mask&errRequiredNotSet > 0 {
return &RequiredNotSetError{}
}
if mask&errInvalidUTF8 > 0 {
return nil
}
// Otherwise return error which can either be nil or fatal.
return err
}

Просмотреть файл

@ -1,16 +1,16 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: jsonpb_test_proto/test_objects.proto
// source: jsonpb_proto/test2.proto
package jsonpb
package jsonpb_proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
any "github.com/golang/protobuf/ptypes/any"
duration "github.com/golang/protobuf/ptypes/duration"
_struct "github.com/golang/protobuf/ptypes/struct"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
wrappers "github.com/golang/protobuf/ptypes/wrappers"
anypb "google.golang.org/protobuf/types/known/anypb"
durationpb "google.golang.org/protobuf/types/known/durationpb"
structpb "google.golang.org/protobuf/types/known/structpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
math "math"
)
@ -65,7 +65,7 @@ func (x *Widget_Color) UnmarshalJSON(data []byte) error {
}
func (Widget_Color) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{3, 0}
return fileDescriptor_50cab1d8463dea41, []int{3, 0}
}
// Test message for holding primitive types.
@ -98,7 +98,7 @@ func (m *Simple) Reset() { *m = Simple{} }
func (m *Simple) String() string { return proto.CompactTextString(m) }
func (*Simple) ProtoMessage() {}
func (*Simple) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{0}
return fileDescriptor_50cab1d8463dea41, []int{0}
}
func (m *Simple) XXX_Unmarshal(b []byte) error {
@ -269,7 +269,7 @@ func (m *NonFinites) Reset() { *m = NonFinites{} }
func (m *NonFinites) String() string { return proto.CompactTextString(m) }
func (*NonFinites) ProtoMessage() {}
func (*NonFinites) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{1}
return fileDescriptor_50cab1d8463dea41, []int{1}
}
func (m *NonFinites) XXX_Unmarshal(b []byte) error {
@ -354,7 +354,7 @@ func (m *Repeats) Reset() { *m = Repeats{} }
func (m *Repeats) String() string { return proto.CompactTextString(m) }
func (*Repeats) ProtoMessage() {}
func (*Repeats) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{2}
return fileDescriptor_50cab1d8463dea41, []int{2}
}
func (m *Repeats) XXX_Unmarshal(b []byte) error {
@ -454,8 +454,8 @@ func (m *Repeats) GetRBytes() [][]byte {
// Test message for holding enums and nested messages.
type Widget struct {
Color *Widget_Color `protobuf:"varint,1,opt,name=color,enum=jsonpb.Widget_Color" json:"color,omitempty"`
RColor []Widget_Color `protobuf:"varint,2,rep,name=r_color,json=rColor,enum=jsonpb.Widget_Color" json:"r_color,omitempty"`
Color *Widget_Color `protobuf:"varint,1,opt,name=color,enum=jsonpb_test.Widget_Color" json:"color,omitempty"`
RColor []Widget_Color `protobuf:"varint,2,rep,name=r_color,json=rColor,enum=jsonpb_test.Widget_Color" json:"r_color,omitempty"`
Simple *Simple `protobuf:"bytes,10,opt,name=simple" json:"simple,omitempty"`
RSimple []*Simple `protobuf:"bytes,11,rep,name=r_simple,json=rSimple" json:"r_simple,omitempty"`
Repeats *Repeats `protobuf:"bytes,20,opt,name=repeats" json:"repeats,omitempty"`
@ -469,7 +469,7 @@ func (m *Widget) Reset() { *m = Widget{} }
func (m *Widget) String() string { return proto.CompactTextString(m) }
func (*Widget) ProtoMessage() {}
func (*Widget) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{3}
return fileDescriptor_50cab1d8463dea41, []int{3}
}
func (m *Widget) XXX_Unmarshal(b []byte) error {
@ -544,7 +544,7 @@ func (m *Maps) Reset() { *m = Maps{} }
func (m *Maps) String() string { return proto.CompactTextString(m) }
func (*Maps) ProtoMessage() {}
func (*Maps) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{4}
return fileDescriptor_50cab1d8463dea41, []int{4}
}
func (m *Maps) XXX_Unmarshal(b []byte) error {
@ -596,7 +596,7 @@ func (m *MsgWithOneof) Reset() { *m = MsgWithOneof{} }
func (m *MsgWithOneof) String() string { return proto.CompactTextString(m) }
func (*MsgWithOneof) ProtoMessage() {}
func (*MsgWithOneof) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{5}
return fileDescriptor_50cab1d8463dea41, []int{5}
}
func (m *MsgWithOneof) XXX_Unmarshal(b []byte) error {
@ -716,7 +716,7 @@ func (m *Real) Reset() { *m = Real{} }
func (m *Real) String() string { return proto.CompactTextString(m) }
func (*Real) ProtoMessage() {}
func (*Real) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{6}
return fileDescriptor_50cab1d8463dea41, []int{6}
}
var extRange_Real = []proto.ExtensionRange{
@ -764,7 +764,7 @@ func (m *Complex) Reset() { *m = Complex{} }
func (m *Complex) String() string { return proto.CompactTextString(m) }
func (*Complex) ProtoMessage() {}
func (*Complex) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{7}
return fileDescriptor_50cab1d8463dea41, []int{7}
}
var extRange_Complex = []proto.ExtensionRange{
@ -804,37 +804,37 @@ var E_Complex_RealExtension = &proto.ExtensionDesc{
ExtendedType: (*Real)(nil),
ExtensionType: (*Complex)(nil),
Field: 123,
Name: "jsonpb.Complex.real_extension",
Name: "jsonpb_test.Complex.real_extension",
Tag: "bytes,123,opt,name=real_extension",
Filename: "jsonpb_test_proto/test_objects.proto",
Filename: "jsonpb_proto/test2.proto",
}
type KnownTypes struct {
An *any.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
Dur *duration.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
St *_struct.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
Ts *timestamp.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
Lv *_struct.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
Val *_struct.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
Dbl *wrappers.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
Flt *wrappers.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
I64 *wrappers.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
U64 *wrappers.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
I32 *wrappers.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
U32 *wrappers.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
Bool *wrappers.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
Str *wrappers.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
Bytes *wrappers.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
An *anypb.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
Dur *durationpb.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
St *structpb.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
Ts *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
Lv *structpb.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
Val *structpb.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
Dbl *wrapperspb.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
Flt *wrapperspb.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
I64 *wrapperspb.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
U64 *wrapperspb.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
I32 *wrapperspb.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
U32 *wrapperspb.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
Bool *wrapperspb.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
Str *wrapperspb.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
Bytes *wrapperspb.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *KnownTypes) Reset() { *m = KnownTypes{} }
func (m *KnownTypes) String() string { return proto.CompactTextString(m) }
func (*KnownTypes) ProtoMessage() {}
func (*KnownTypes) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{8}
return fileDescriptor_50cab1d8463dea41, []int{8}
}
func (m *KnownTypes) XXX_Unmarshal(b []byte) error {
@ -855,105 +855,105 @@ func (m *KnownTypes) XXX_DiscardUnknown() {
var xxx_messageInfo_KnownTypes proto.InternalMessageInfo
func (m *KnownTypes) GetAn() *any.Any {
func (m *KnownTypes) GetAn() *anypb.Any {
if m != nil {
return m.An
}
return nil
}
func (m *KnownTypes) GetDur() *duration.Duration {
func (m *KnownTypes) GetDur() *durationpb.Duration {
if m != nil {
return m.Dur
}
return nil
}
func (m *KnownTypes) GetSt() *_struct.Struct {
func (m *KnownTypes) GetSt() *structpb.Struct {
if m != nil {
return m.St
}
return nil
}
func (m *KnownTypes) GetTs() *timestamp.Timestamp {
func (m *KnownTypes) GetTs() *timestamppb.Timestamp {
if m != nil {
return m.Ts
}
return nil
}
func (m *KnownTypes) GetLv() *_struct.ListValue {
func (m *KnownTypes) GetLv() *structpb.ListValue {
if m != nil {
return m.Lv
}
return nil
}
func (m *KnownTypes) GetVal() *_struct.Value {
func (m *KnownTypes) GetVal() *structpb.Value {
if m != nil {
return m.Val
}
return nil
}
func (m *KnownTypes) GetDbl() *wrappers.DoubleValue {
func (m *KnownTypes) GetDbl() *wrapperspb.DoubleValue {
if m != nil {
return m.Dbl
}
return nil
}
func (m *KnownTypes) GetFlt() *wrappers.FloatValue {
func (m *KnownTypes) GetFlt() *wrapperspb.FloatValue {
if m != nil {
return m.Flt
}
return nil
}
func (m *KnownTypes) GetI64() *wrappers.Int64Value {
func (m *KnownTypes) GetI64() *wrapperspb.Int64Value {
if m != nil {
return m.I64
}
return nil
}
func (m *KnownTypes) GetU64() *wrappers.UInt64Value {
func (m *KnownTypes) GetU64() *wrapperspb.UInt64Value {
if m != nil {
return m.U64
}
return nil
}
func (m *KnownTypes) GetI32() *wrappers.Int32Value {
func (m *KnownTypes) GetI32() *wrapperspb.Int32Value {
if m != nil {
return m.I32
}
return nil
}
func (m *KnownTypes) GetU32() *wrappers.UInt32Value {
func (m *KnownTypes) GetU32() *wrapperspb.UInt32Value {
if m != nil {
return m.U32
}
return nil
}
func (m *KnownTypes) GetBool() *wrappers.BoolValue {
func (m *KnownTypes) GetBool() *wrapperspb.BoolValue {
if m != nil {
return m.Bool
}
return nil
}
func (m *KnownTypes) GetStr() *wrappers.StringValue {
func (m *KnownTypes) GetStr() *wrapperspb.StringValue {
if m != nil {
return m.Str
}
return nil
}
func (m *KnownTypes) GetBytes() *wrappers.BytesValue {
func (m *KnownTypes) GetBytes() *wrapperspb.BytesValue {
if m != nil {
return m.Bytes
}
@ -972,7 +972,7 @@ func (m *MsgWithRequired) Reset() { *m = MsgWithRequired{} }
func (m *MsgWithRequired) String() string { return proto.CompactTextString(m) }
func (*MsgWithRequired) ProtoMessage() {}
func (*MsgWithRequired) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{9}
return fileDescriptor_50cab1d8463dea41, []int{9}
}
func (m *MsgWithRequired) XXX_Unmarshal(b []byte) error {
@ -1013,7 +1013,7 @@ func (m *MsgWithIndirectRequired) Reset() { *m = MsgWithIndirectRequired
func (m *MsgWithIndirectRequired) String() string { return proto.CompactTextString(m) }
func (*MsgWithIndirectRequired) ProtoMessage() {}
func (*MsgWithIndirectRequired) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{10}
return fileDescriptor_50cab1d8463dea41, []int{10}
}
func (m *MsgWithIndirectRequired) XXX_Unmarshal(b []byte) error {
@ -1066,7 +1066,7 @@ func (m *MsgWithRequiredBytes) Reset() { *m = MsgWithRequiredBytes{} }
func (m *MsgWithRequiredBytes) String() string { return proto.CompactTextString(m) }
func (*MsgWithRequiredBytes) ProtoMessage() {}
func (*MsgWithRequiredBytes) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{11}
return fileDescriptor_50cab1d8463dea41, []int{11}
}
func (m *MsgWithRequiredBytes) XXX_Unmarshal(b []byte) error {
@ -1095,17 +1095,17 @@ func (m *MsgWithRequiredBytes) GetByts() []byte {
}
type MsgWithRequiredWKT struct {
Str *wrappers.StringValue `protobuf:"bytes,1,req,name=str" json:"str,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Str *wrapperspb.StringValue `protobuf:"bytes,1,req,name=str" json:"str,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MsgWithRequiredWKT) Reset() { *m = MsgWithRequiredWKT{} }
func (m *MsgWithRequiredWKT) String() string { return proto.CompactTextString(m) }
func (*MsgWithRequiredWKT) ProtoMessage() {}
func (*MsgWithRequiredWKT) Descriptor() ([]byte, []int) {
return fileDescriptor_6b3d96f97365f06c, []int{12}
return fileDescriptor_50cab1d8463dea41, []int{12}
}
func (m *MsgWithRequiredWKT) XXX_Unmarshal(b []byte) error {
@ -1126,7 +1126,7 @@ func (m *MsgWithRequiredWKT) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgWithRequiredWKT proto.InternalMessageInfo
func (m *MsgWithRequiredWKT) GetStr() *wrappers.StringValue {
func (m *MsgWithRequiredWKT) GetStr() *wrapperspb.StringValue {
if m != nil {
return m.Str
}
@ -1137,141 +1137,140 @@ var E_Name = &proto.ExtensionDesc{
ExtendedType: (*Real)(nil),
ExtensionType: (*string)(nil),
Field: 124,
Name: "jsonpb.name",
Name: "jsonpb_test.name",
Tag: "bytes,124,opt,name=name",
Filename: "jsonpb_test_proto/test_objects.proto",
Filename: "jsonpb_proto/test2.proto",
}
var E_Extm = &proto.ExtensionDesc{
ExtendedType: (*Real)(nil),
ExtensionType: (*MsgWithRequired)(nil),
Field: 125,
Name: "jsonpb.extm",
Name: "jsonpb_test.extm",
Tag: "bytes,125,opt,name=extm",
Filename: "jsonpb_test_proto/test_objects.proto",
Filename: "jsonpb_proto/test2.proto",
}
func init() {
proto.RegisterEnum("jsonpb.Widget_Color", Widget_Color_name, Widget_Color_value)
proto.RegisterType((*Simple)(nil), "jsonpb.Simple")
proto.RegisterType((*NonFinites)(nil), "jsonpb.NonFinites")
proto.RegisterType((*Repeats)(nil), "jsonpb.Repeats")
proto.RegisterType((*Widget)(nil), "jsonpb.Widget")
proto.RegisterType((*Maps)(nil), "jsonpb.Maps")
proto.RegisterMapType((map[bool]*Simple)(nil), "jsonpb.Maps.MBoolSimpleEntry")
proto.RegisterMapType((map[int64]string)(nil), "jsonpb.Maps.MInt64StrEntry")
proto.RegisterType((*MsgWithOneof)(nil), "jsonpb.MsgWithOneof")
proto.RegisterType((*Real)(nil), "jsonpb.Real")
proto.RegisterEnum("jsonpb_test.Widget_Color", Widget_Color_name, Widget_Color_value)
proto.RegisterType((*Simple)(nil), "jsonpb_test.Simple")
proto.RegisterType((*NonFinites)(nil), "jsonpb_test.NonFinites")
proto.RegisterType((*Repeats)(nil), "jsonpb_test.Repeats")
proto.RegisterType((*Widget)(nil), "jsonpb_test.Widget")
proto.RegisterType((*Maps)(nil), "jsonpb_test.Maps")
proto.RegisterMapType((map[bool]*Simple)(nil), "jsonpb_test.Maps.MBoolSimpleEntry")
proto.RegisterMapType((map[int64]string)(nil), "jsonpb_test.Maps.MInt64StrEntry")
proto.RegisterType((*MsgWithOneof)(nil), "jsonpb_test.MsgWithOneof")
proto.RegisterType((*Real)(nil), "jsonpb_test.Real")
proto.RegisterExtension(E_Complex_RealExtension)
proto.RegisterType((*Complex)(nil), "jsonpb.Complex")
proto.RegisterType((*KnownTypes)(nil), "jsonpb.KnownTypes")
proto.RegisterType((*MsgWithRequired)(nil), "jsonpb.MsgWithRequired")
proto.RegisterType((*MsgWithIndirectRequired)(nil), "jsonpb.MsgWithIndirectRequired")
proto.RegisterMapType((map[string]*MsgWithRequired)(nil), "jsonpb.MsgWithIndirectRequired.MapFieldEntry")
proto.RegisterType((*MsgWithRequiredBytes)(nil), "jsonpb.MsgWithRequiredBytes")
proto.RegisterType((*MsgWithRequiredWKT)(nil), "jsonpb.MsgWithRequiredWKT")
proto.RegisterType((*Complex)(nil), "jsonpb_test.Complex")
proto.RegisterType((*KnownTypes)(nil), "jsonpb_test.KnownTypes")
proto.RegisterType((*MsgWithRequired)(nil), "jsonpb_test.MsgWithRequired")
proto.RegisterType((*MsgWithIndirectRequired)(nil), "jsonpb_test.MsgWithIndirectRequired")
proto.RegisterMapType((map[string]*MsgWithRequired)(nil), "jsonpb_test.MsgWithIndirectRequired.MapFieldEntry")
proto.RegisterType((*MsgWithRequiredBytes)(nil), "jsonpb_test.MsgWithRequiredBytes")
proto.RegisterType((*MsgWithRequiredWKT)(nil), "jsonpb_test.MsgWithRequiredWKT")
proto.RegisterExtension(E_Name)
proto.RegisterExtension(E_Extm)
}
func init() {
proto.RegisterFile("jsonpb_test_proto/test_objects.proto", fileDescriptor_6b3d96f97365f06c)
}
func init() { proto.RegisterFile("jsonpb_proto/test2.proto", fileDescriptor_50cab1d8463dea41) }
var fileDescriptor_6b3d96f97365f06c = []byte{
// 1504 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdd, 0x72, 0xdb, 0xb8,
0x15, 0x36, 0x49, 0x51, 0x12, 0x8f, 0xfc, 0x17, 0xc4, 0x49, 0x64, 0x37, 0x4d, 0x39, 0x4a, 0x9a,
0xaa, 0x49, 0x2d, 0x4f, 0x65, 0x8d, 0x26, 0x75, 0x72, 0x13, 0xc7, 0x4e, 0x93, 0x26, 0x71, 0x3b,
0xb0, 0xd3, 0xcc, 0xf4, 0x46, 0x43, 0x99, 0x94, 0xcc, 0x94, 0x24, 0x54, 0x00, 0xb2, 0xa3, 0xe9,
0xee, 0x8c, 0x9f, 0x61, 0x67, 0x9f, 0x60, 0x2f, 0xf6, 0x76, 0xef, 0xf6, 0x62, 0xdf, 0x62, 0xdf,
0x68, 0x07, 0x07, 0xa0, 0x7e, 0xad, 0xd9, 0xbd, 0xb2, 0x80, 0xef, 0x07, 0x20, 0xce, 0xc7, 0x03,
0x1a, 0x1e, 0x7d, 0x16, 0x2c, 0x1b, 0x74, 0x3b, 0x32, 0x12, 0xb2, 0x33, 0xe0, 0x4c, 0xb2, 0x3d,
0xfc, 0xc9, 0xba, 0x9f, 0xa3, 0x73, 0x29, 0x1a, 0x38, 0x45, 0x8a, 0x9a, 0xb5, 0xb3, 0xdd, 0x67,
0xac, 0x9f, 0x44, 0x7b, 0x38, 0xdb, 0x1d, 0xf6, 0xf6, 0x82, 0x6c, 0xa4, 0x29, 0x3b, 0x0f, 0xe6,
0xa1, 0x70, 0xc8, 0x03, 0x19, 0xb3, 0xcc, 0xe0, 0xf7, 0xe7, 0x71, 0x21, 0xf9, 0xf0, 0x5c, 0x1a,
0xf4, 0x0f, 0xf3, 0xa8, 0x8c, 0xd3, 0x48, 0xc8, 0x20, 0x1d, 0x2c, 0xb3, 0xbf, 0xe2, 0xc1, 0x60,
0x10, 0x71, 0xb3, 0xc3, 0xda, 0x0f, 0x05, 0x28, 0x9e, 0xc6, 0xe9, 0x20, 0x89, 0xc8, 0x1d, 0x28,
0xb2, 0x4e, 0x97, 0xb1, 0xa4, 0x6a, 0xf9, 0x56, 0xbd, 0x4c, 0x5d, 0x76, 0xc8, 0x58, 0x42, 0xee,
0x41, 0x89, 0x75, 0xe2, 0x4c, 0xee, 0x37, 0xab, 0xb6, 0x6f, 0xd5, 0x5d, 0x5a, 0x64, 0x6f, 0xd5,
0x88, 0x3c, 0x80, 0x8a, 0x01, 0x3a, 0x42, 0xf2, 0xaa, 0x83, 0xa0, 0xa7, 0xc1, 0x53, 0xc9, 0xc7,
0xc2, 0x76, 0xab, 0x5a, 0xf0, 0xad, 0xba, 0xa3, 0x85, 0xed, 0xd6, 0x58, 0xd8, 0x6e, 0xa1, 0xd0,
0x45, 0xd0, 0xd3, 0xa0, 0x12, 0x6e, 0x43, 0x99, 0x75, 0x86, 0x7a, 0xc9, 0xa2, 0x6f, 0xd5, 0xd7,
0x68, 0x89, 0x7d, 0xc4, 0x21, 0xf1, 0x61, 0x35, 0x87, 0x50, 0x5b, 0x42, 0x18, 0x0c, 0x3c, 0x23,
0x6e, 0xb7, 0xaa, 0x65, 0xdf, 0xaa, 0x17, 0x8c, 0xb8, 0xdd, 0x9a, 0x88, 0xcd, 0xc2, 0x1e, 0xc2,
0x60, 0xe0, 0xb1, 0x58, 0xe8, 0x95, 0xc1, 0xb7, 0xea, 0xb7, 0x68, 0x89, 0x9d, 0x4e, 0xad, 0x2c,
0x26, 0x2b, 0x57, 0x10, 0x06, 0x03, 0xcf, 0x88, 0xdb, 0xad, 0xea, 0xaa, 0x6f, 0xd5, 0x89, 0x11,
0xe7, 0x2b, 0x8b, 0xc9, 0xca, 0x6b, 0x08, 0x83, 0x81, 0xc7, 0x87, 0xd5, 0x4b, 0x58, 0x20, 0xab,
0xeb, 0xbe, 0x55, 0xb7, 0x69, 0x91, 0xbd, 0x56, 0x23, 0x7d, 0x58, 0x08, 0xa0, 0x72, 0x03, 0x41,
0x4f, 0x83, 0xe3, 0x55, 0x43, 0x36, 0xec, 0x26, 0x51, 0x75, 0xd3, 0xb7, 0xea, 0x16, 0x2d, 0xb1,
0x23, 0x1c, 0xea, 0x55, 0x35, 0x84, 0xda, 0x5b, 0x08, 0x83, 0x81, 0x27, 0x5b, 0x96, 0x3c, 0xce,
0xfa, 0x55, 0xe2, 0x5b, 0x75, 0x4f, 0x6d, 0x19, 0x87, 0x7a, 0x43, 0xdd, 0x91, 0x8c, 0x44, 0xf5,
0xb6, 0x6f, 0xd5, 0x57, 0x69, 0x91, 0x1d, 0xaa, 0x51, 0xed, 0x1b, 0x0b, 0xe0, 0x84, 0x65, 0xaf,
0xe3, 0x2c, 0x96, 0x91, 0x20, 0xb7, 0xc1, 0xed, 0x75, 0xb2, 0x20, 0xc3, 0xd0, 0xd8, 0xb4, 0xd0,
0x3b, 0x09, 0x32, 0x15, 0xa5, 0x5e, 0x67, 0x10, 0x67, 0x3d, 0x8c, 0x8c, 0x4d, 0xdd, 0xde, 0xbf,
0xe2, 0xac, 0xa7, 0xa7, 0x33, 0x35, 0xed, 0x98, 0xe9, 0x13, 0x35, 0x7d, 0x1b, 0xdc, 0x10, 0x2d,
0x0a, 0xb8, 0xc1, 0x42, 0x68, 0x2c, 0x42, 0x6d, 0xe1, 0xe2, 0xac, 0x1b, 0xe6, 0x16, 0xa1, 0xb6,
0x28, 0x9a, 0x69, 0x65, 0x51, 0xfb, 0xde, 0x86, 0x12, 0x8d, 0x06, 0x51, 0x20, 0x85, 0xa2, 0xf0,
0x3c, 0xc7, 0x8e, 0xca, 0x31, 0xcf, 0x73, 0xcc, 0xc7, 0x39, 0x76, 0x54, 0x8e, 0xb9, 0xce, 0x71,
0x0e, 0xb4, 0x5b, 0x55, 0xc7, 0x77, 0x54, 0x4e, 0xb9, 0xce, 0xe9, 0x36, 0x94, 0x79, 0x9e, 0xc3,
0x82, 0xef, 0xa8, 0x1c, 0x72, 0x93, 0xc3, 0x31, 0xd4, 0x6e, 0x55, 0x5d, 0xdf, 0x51, 0x29, 0xe3,
0x26, 0x65, 0x08, 0x89, 0x3c, 0xbd, 0x8e, 0xca, 0x10, 0x3f, 0x9d, 0x52, 0x99, 0x84, 0x94, 0x7c,
0x47, 0x25, 0x84, 0x9b, 0x84, 0xe0, 0x26, 0x74, 0xfd, 0xcb, 0xbe, 0xa3, 0xea, 0xcf, 0x75, 0xfd,
0x51, 0x63, 0xea, 0xeb, 0xf9, 0x8e, 0xaa, 0x2f, 0x37, 0xf5, 0xd5, 0x76, 0xba, 0x7a, 0xe0, 0x3b,
0xaa, 0x7a, 0x7c, 0x52, 0x3d, 0x6e, 0xaa, 0x57, 0xf1, 0x1d, 0x55, 0x3d, 0xae, 0xab, 0xf7, 0xa3,
0x0d, 0xc5, 0x4f, 0x71, 0xd8, 0x8f, 0x24, 0x79, 0x02, 0xee, 0x39, 0x4b, 0x18, 0xc7, 0xca, 0xad,
0x37, 0xb7, 0x1a, 0xba, 0x59, 0x35, 0x34, 0xdc, 0x78, 0xa5, 0x30, 0xaa, 0x29, 0x64, 0x57, 0xf9,
0x69, 0xb6, 0x3a, 0xbc, 0x65, 0xec, 0x22, 0xc7, 0xbf, 0xe4, 0x31, 0x14, 0x05, 0x36, 0x15, 0x7c,
0x8b, 0x2a, 0xcd, 0xf5, 0x9c, 0xad, 0x5b, 0x0d, 0x35, 0x28, 0xf9, 0xb3, 0x3e, 0x10, 0x64, 0xaa,
0x7d, 0x2e, 0x32, 0xd5, 0x01, 0x19, 0x6a, 0x89, 0xeb, 0x02, 0x57, 0xb7, 0xd0, 0x73, 0x23, 0x67,
0x9a, 0xba, 0xd3, 0x1c, 0x27, 0x7f, 0x01, 0x8f, 0x77, 0x72, 0xf2, 0x1d, 0xb4, 0x5d, 0x20, 0x97,
0xb9, 0xf9, 0x55, 0xfb, 0x23, 0xb8, 0x7a, 0xd3, 0x25, 0x70, 0xe8, 0xf1, 0xd1, 0xe6, 0x0a, 0xf1,
0xc0, 0xfd, 0x3b, 0x3d, 0x3e, 0x3e, 0xd9, 0xb4, 0x48, 0x19, 0x0a, 0x87, 0xef, 0x3f, 0x1e, 0x6f,
0xda, 0xb5, 0x6f, 0x6d, 0x28, 0x7c, 0x08, 0x06, 0x82, 0x3c, 0x87, 0x4a, 0x3a, 0xd5, 0xbd, 0x2c,
0xf4, 0xff, 0x5d, 0xee, 0xaf, 0x28, 0x8d, 0x0f, 0x79, 0x2b, 0x3b, 0xce, 0x24, 0x1f, 0x51, 0x2f,
0x1d, 0xb7, 0xb6, 0x97, 0xb0, 0x96, 0x62, 0x36, 0xf3, 0xa7, 0xb6, 0x51, 0xfe, 0xfb, 0x59, 0xb9,
0xca, 0xab, 0x7e, 0x6c, 0x6d, 0x50, 0x49, 0x27, 0x33, 0x3b, 0x2f, 0x60, 0x7d, 0xd6, 0x9f, 0x6c,
0x82, 0xf3, 0xdf, 0x68, 0x84, 0x65, 0x74, 0xa8, 0xfa, 0x49, 0xb6, 0xc0, 0xbd, 0x0c, 0x92, 0x61,
0x84, 0xaf, 0x9f, 0x47, 0xf5, 0xe0, 0xc0, 0x7e, 0x66, 0xed, 0x9c, 0xc0, 0xe6, 0xbc, 0xfd, 0xb4,
0xbe, 0xac, 0xf5, 0x8f, 0xa6, 0xf5, 0x8b, 0x45, 0x99, 0xf8, 0xd5, 0x7e, 0xb6, 0x60, 0xf5, 0x83,
0xe8, 0x7f, 0x8a, 0xe5, 0xc5, 0x3f, 0xb3, 0x88, 0xf5, 0xc8, 0x5d, 0x70, 0x65, 0x2c, 0x93, 0x08,
0xed, 0xbc, 0x37, 0x2b, 0x54, 0x0f, 0x49, 0x15, 0x8a, 0x22, 0x48, 0x02, 0x3e, 0x42, 0x4f, 0xe7,
0xcd, 0x0a, 0x35, 0x63, 0xb2, 0x03, 0xa5, 0x57, 0x6c, 0xa8, 0x76, 0x82, 0x6d, 0x41, 0x69, 0xf2,
0x09, 0xf2, 0x10, 0x56, 0x2f, 0x58, 0x1a, 0x75, 0x82, 0x30, 0xe4, 0x91, 0x10, 0xd8, 0x21, 0x14,
0xa1, 0xa2, 0x66, 0x5f, 0xea, 0x49, 0x72, 0x0c, 0xb7, 0x52, 0xd1, 0xef, 0x5c, 0xc5, 0xf2, 0xa2,
0xc3, 0xa3, 0xff, 0x0d, 0x63, 0x1e, 0x85, 0xd8, 0x35, 0x2a, 0xcd, 0x7b, 0xe3, 0x83, 0xd5, 0x7b,
0xa4, 0x06, 0x7e, 0xb3, 0x42, 0x37, 0xd2, 0xd9, 0xa9, 0xc3, 0x12, 0xb8, 0xc3, 0x2c, 0x66, 0x59,
0xed, 0x31, 0x14, 0x68, 0x14, 0x24, 0x93, 0x53, 0xb4, 0x74, 0xab, 0xc1, 0xc1, 0x93, 0x72, 0x39,
0xdc, 0xbc, 0xbe, 0xbe, 0xbe, 0xb6, 0x6b, 0x57, 0x6a, 0xe3, 0xea, 0x40, 0xbe, 0x90, 0xfb, 0xe0,
0xc5, 0x69, 0xd0, 0x8f, 0x33, 0xf5, 0x80, 0x9a, 0x3e, 0x99, 0x98, 0x48, 0x9a, 0x47, 0xb0, 0xce,
0xa3, 0x20, 0xe9, 0x44, 0x5f, 0x64, 0x94, 0x89, 0x98, 0x65, 0x64, 0x75, 0x92, 0xcc, 0x20, 0xa9,
0xfe, 0x7f, 0x36, 0xda, 0xc6, 0x9e, 0xae, 0x29, 0xd1, 0x71, 0xae, 0xa9, 0xfd, 0xe4, 0x02, 0xbc,
0xcb, 0xd8, 0x55, 0x76, 0x36, 0x1a, 0x44, 0x82, 0x3c, 0x02, 0x3b, 0xc8, 0xf0, 0xda, 0xa8, 0x34,
0xb7, 0x1a, 0xfa, 0xc2, 0x6f, 0xe4, 0x17, 0x7e, 0xe3, 0x65, 0x36, 0xa2, 0x76, 0x90, 0x91, 0xa7,
0xe0, 0x84, 0x43, 0xfd, 0xb2, 0x57, 0x9a, 0xdb, 0x0b, 0xb4, 0x23, 0xf3, 0xd9, 0x41, 0x15, 0x8b,
0xfc, 0x09, 0x6c, 0x21, 0xf1, 0x16, 0x53, 0x67, 0x38, 0xcf, 0x3d, 0xc5, 0x4f, 0x10, 0x6a, 0x0b,
0xd5, 0x44, 0x6c, 0x29, 0x4c, 0x4c, 0x76, 0x16, 0x88, 0x67, 0xf9, 0xd7, 0x08, 0xb5, 0xa5, 0x50,
0xdc, 0xe4, 0x12, 0x6f, 0xb0, 0x9b, 0xb8, 0xef, 0x63, 0x21, 0xff, 0xad, 0x4e, 0x98, 0xda, 0xc9,
0x25, 0xa9, 0x83, 0x73, 0x19, 0x24, 0x78, 0xa3, 0x55, 0x9a, 0x77, 0x17, 0xc8, 0x9a, 0xa8, 0x28,
0xa4, 0x01, 0x4e, 0xd8, 0x4d, 0x30, 0x3a, 0x95, 0xe6, 0xfd, 0xc5, 0xe7, 0xc2, 0x5e, 0x69, 0xf8,
0x61, 0x37, 0x21, 0xbb, 0xe0, 0xf4, 0x12, 0x89, 0x49, 0x52, 0xef, 0xed, 0x3c, 0x1f, 0xbb, 0xae,
0xa1, 0xf7, 0x12, 0xa9, 0xe8, 0x31, 0x36, 0xf9, 0x9b, 0xe9, 0xf8, 0x26, 0x1a, 0x7a, 0xdc, 0x6e,
0xa9, 0xdd, 0x0c, 0xdb, 0x2d, 0xbc, 0x9c, 0x6e, 0xda, 0xcd, 0xc7, 0x69, 0xfe, 0xb0, 0xdd, 0x42,
0xfb, 0xfd, 0x26, 0x7e, 0xc7, 0x2c, 0xb1, 0xdf, 0x6f, 0xe6, 0xf6, 0xfb, 0x4d, 0xb4, 0xdf, 0x6f,
0xe2, 0x87, 0xcd, 0x32, 0xfb, 0x31, 0x7f, 0x88, 0xfc, 0x02, 0xde, 0x84, 0xde, 0x92, 0x43, 0x57,
0xad, 0x40, 0xd3, 0x91, 0xa7, 0xfc, 0x55, 0x53, 0x83, 0x25, 0xfe, 0xfa, 0x76, 0x31, 0xfe, 0x42,
0x72, 0xf2, 0x57, 0x70, 0xf3, 0x5b, 0xe6, 0xe6, 0x07, 0xc0, 0x5b, 0x47, 0x0b, 0x34, 0xb3, 0xf6,
0x10, 0x36, 0xe6, 0x5e, 0x46, 0xd5, 0x80, 0x74, 0x2b, 0xb5, 0xeb, 0x1e, 0xfa, 0xd6, 0xbe, 0xb3,
0xe1, 0x9e, 0x61, 0xbd, 0xcd, 0xc2, 0x98, 0x47, 0xe7, 0x72, 0xcc, 0x7e, 0x0a, 0x05, 0x31, 0xec,
0xa6, 0x26, 0xc9, 0xcb, 0xde, 0x70, 0x8a, 0x24, 0xf2, 0x0f, 0xf0, 0xd2, 0x60, 0xd0, 0xe9, 0xc5,
0x51, 0x12, 0x9a, 0x66, 0xbb, 0x3b, 0xa7, 0x98, 0x5f, 0x40, 0x35, 0xe1, 0xd7, 0x8a, 0xaf, 0x9b,
0x6f, 0x39, 0x35, 0x43, 0xf2, 0x0c, 0x2a, 0x22, 0x89, 0xcf, 0x23, 0xe3, 0xe6, 0xa0, 0xdb, 0xd2,
0xf5, 0x01, 0xb9, 0xa8, 0xdc, 0x39, 0x83, 0xb5, 0x19, 0xd3, 0xe9, 0x96, 0xeb, 0xe9, 0x96, 0xbb,
0x3b, 0xdb, 0x72, 0x97, 0xda, 0x4e, 0xf5, 0xde, 0x27, 0xb0, 0x35, 0x87, 0xe2, 0x69, 0x13, 0x02,
0x85, 0xee, 0x48, 0x0a, 0x3c, 0xcf, 0x55, 0x8a, 0xbf, 0x6b, 0x47, 0x40, 0xe6, 0xb8, 0x9f, 0xde,
0x9d, 0xe5, 0xe5, 0x56, 0xc4, 0xdf, 0x52, 0xee, 0x03, 0x1f, 0x0a, 0x59, 0x90, 0x46, 0x73, 0x4d,
0xeb, 0x2b, 0x7c, 0x0a, 0x44, 0x0e, 0xfe, 0x06, 0x85, 0xe8, 0x8b, 0x4c, 0xe7, 0x18, 0x5f, 0xff,
0x4a, 0xa9, 0x94, 0xe4, 0xf0, 0xc5, 0x7f, 0x0e, 0xfa, 0xb1, 0xbc, 0x18, 0x76, 0x1b, 0xe7, 0x2c,
0xdd, 0xeb, 0xb3, 0x24, 0xc8, 0xfa, 0x93, 0xff, 0x5b, 0xb4, 0x74, 0x6f, 0xe1, 0xdf, 0xae, 0xe7,
0x7a, 0xe6, 0x97, 0x00, 0x00, 0x00, 0xff, 0xff, 0x66, 0xc2, 0xb5, 0xb6, 0x91, 0x0d, 0x00, 0x00,
var fileDescriptor_50cab1d8463dea41 = []byte{
// 1510 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdd, 0x6e, 0xdb, 0x46,
0x16, 0x36, 0x49, 0x51, 0x12, 0x8f, 0x6c, 0xc7, 0x1e, 0x3b, 0x09, 0xed, 0x0d, 0xb2, 0x84, 0xb2,
0xd9, 0xd5, 0x26, 0x58, 0x79, 0x43, 0x0b, 0x42, 0x91, 0x36, 0x40, 0xe3, 0xd8, 0x6e, 0xd2, 0x24,
0x4e, 0x41, 0x27, 0x0d, 0xda, 0x1b, 0x81, 0x32, 0x29, 0x99, 0x2d, 0xc9, 0x51, 0x67, 0x46, 0x4e,
0x84, 0xb6, 0x80, 0xfb, 0x0a, 0x7d, 0x85, 0x02, 0xbd, 0xed, 0x5d, 0x2f, 0xfa, 0x1c, 0x45, 0x9f,
0xa7, 0x98, 0x33, 0x43, 0xfd, 0x59, 0x36, 0x72, 0x65, 0xcd, 0x7c, 0x3f, 0x33, 0x9c, 0xf3, 0xf1,
0x0c, 0x0d, 0xee, 0x37, 0x9c, 0xe6, 0x83, 0x6e, 0x67, 0xc0, 0xa8, 0xa0, 0x3b, 0x22, 0xe6, 0xc2,
0x6f, 0xe2, 0x6f, 0x52, 0xd3, 0x88, 0x9c, 0xdb, 0xde, 0xea, 0x53, 0xda, 0x4f, 0xe3, 0x1d, 0x84,
0xba, 0xc3, 0xde, 0x4e, 0x98, 0x8f, 0x14, 0x6f, 0xfb, 0xf6, 0x3c, 0x14, 0x0d, 0x59, 0x28, 0x12,
0x9a, 0x6b, 0xfc, 0xd6, 0x3c, 0xce, 0x05, 0x1b, 0x9e, 0x08, 0x8d, 0xfe, 0x73, 0x1e, 0x15, 0x49,
0x16, 0x73, 0x11, 0x66, 0x83, 0xcb, 0xec, 0xdf, 0xb1, 0x70, 0x30, 0x88, 0x19, 0x57, 0x78, 0xfd,
0xb7, 0x12, 0x94, 0x8f, 0x93, 0x6c, 0x90, 0xc6, 0xe4, 0x3a, 0x94, 0x69, 0xa7, 0x4b, 0x69, 0xea,
0x1a, 0x9e, 0xd1, 0xa8, 0x06, 0x36, 0xdd, 0xa3, 0x34, 0x25, 0x37, 0xa1, 0x42, 0x3b, 0x49, 0x2e,
0x76, 0x7d, 0xd7, 0xf4, 0x8c, 0x86, 0x1d, 0x94, 0xe9, 0x33, 0x39, 0x22, 0xb7, 0xa1, 0xa6, 0x81,
0x0e, 0x17, 0xcc, 0xb5, 0x10, 0x74, 0x14, 0x78, 0x2c, 0xd8, 0x58, 0xd8, 0x6e, 0xb9, 0x25, 0xcf,
0x68, 0x58, 0x4a, 0xd8, 0x6e, 0x8d, 0x85, 0xed, 0x16, 0x0a, 0x6d, 0x04, 0x1d, 0x05, 0x4a, 0xe1,
0x16, 0x54, 0x69, 0x67, 0xa8, 0x96, 0x2c, 0x7b, 0x46, 0x63, 0x25, 0xa8, 0xd0, 0x37, 0x38, 0x24,
0x1e, 0x2c, 0x17, 0x10, 0x6a, 0x2b, 0x08, 0x83, 0x86, 0x67, 0xc4, 0xed, 0x96, 0x5b, 0xf5, 0x8c,
0x46, 0x49, 0x8b, 0xdb, 0xad, 0x89, 0x58, 0x2f, 0xec, 0x20, 0x0c, 0x1a, 0x1e, 0x8b, 0xb9, 0x5a,
0x19, 0x3c, 0xa3, 0xb1, 0x1e, 0x54, 0xe8, 0xf1, 0xd4, 0xca, 0x7c, 0xb2, 0x72, 0x0d, 0x61, 0xd0,
0xf0, 0x8c, 0xb8, 0xdd, 0x72, 0x97, 0x3d, 0xa3, 0x41, 0xb4, 0xb8, 0x58, 0x99, 0x4f, 0x56, 0x5e,
0x41, 0x18, 0x34, 0x3c, 0x3e, 0xac, 0x5e, 0x4a, 0x43, 0xe1, 0xae, 0x7a, 0x46, 0xc3, 0x0c, 0xca,
0xf4, 0x50, 0x8e, 0xd4, 0x61, 0x21, 0x80, 0xca, 0x6b, 0x08, 0x3a, 0x0a, 0x1c, 0xaf, 0x1a, 0xd1,
0x61, 0x37, 0x8d, 0xdd, 0x35, 0xcf, 0x68, 0x18, 0x41, 0x85, 0xee, 0xe3, 0x50, 0xad, 0xaa, 0x20,
0xd4, 0xae, 0x23, 0x0c, 0x1a, 0x9e, 0x6c, 0x59, 0xb0, 0x24, 0xef, 0xbb, 0xc4, 0x33, 0x1a, 0x8e,
0xdc, 0x32, 0x0e, 0xd5, 0x86, 0xba, 0x23, 0x11, 0x73, 0x77, 0xc3, 0x33, 0x1a, 0xcb, 0x41, 0x99,
0xee, 0xc9, 0x51, 0xfd, 0x67, 0x03, 0xe0, 0x88, 0xe6, 0x87, 0x49, 0x9e, 0x88, 0x98, 0x93, 0x0d,
0xb0, 0x7b, 0x9d, 0x3c, 0xcc, 0x31, 0x34, 0x66, 0x50, 0xea, 0x1d, 0x85, 0xb9, 0x8c, 0x52, 0xaf,
0x33, 0x48, 0xf2, 0x1e, 0x46, 0xc6, 0x0c, 0xec, 0xde, 0x17, 0x49, 0xde, 0x53, 0xd3, 0xb9, 0x9c,
0xb6, 0xf4, 0xf4, 0x91, 0x9c, 0xde, 0x00, 0x3b, 0x42, 0x8b, 0x12, 0x6e, 0xb0, 0x14, 0x69, 0x8b,
0x48, 0x59, 0xd8, 0x38, 0x6b, 0x47, 0x85, 0x45, 0xa4, 0x2c, 0xca, 0x7a, 0x5a, 0x5a, 0xd4, 0x7f,
0x35, 0xa1, 0x12, 0xc4, 0x83, 0x38, 0x14, 0x5c, 0x52, 0x58, 0x91, 0x63, 0x4b, 0xe6, 0x98, 0x15,
0x39, 0x66, 0xe3, 0x1c, 0x5b, 0x32, 0xc7, 0x4c, 0xe5, 0xb8, 0x00, 0xda, 0x2d, 0xd7, 0xf2, 0x2c,
0x99, 0x53, 0xa6, 0x72, 0xba, 0x05, 0x55, 0x56, 0xe4, 0xb0, 0xe4, 0x59, 0x32, 0x87, 0x4c, 0xe7,
0x70, 0x0c, 0xb5, 0x5b, 0xae, 0xed, 0x59, 0x32, 0x65, 0x4c, 0xa7, 0x0c, 0x21, 0x5e, 0xa4, 0xd7,
0x92, 0x19, 0x62, 0xc7, 0x53, 0x2a, 0x9d, 0x90, 0x8a, 0x67, 0xc9, 0x84, 0x30, 0x9d, 0x10, 0xdc,
0x84, 0xaa, 0x7f, 0xd5, 0xb3, 0x64, 0xfd, 0x99, 0xaa, 0x3f, 0x6a, 0x74, 0x7d, 0x1d, 0xcf, 0x92,
0xf5, 0x65, 0xba, 0xbe, 0xca, 0x4e, 0x55, 0x0f, 0x3c, 0x4b, 0x56, 0x8f, 0x4d, 0xaa, 0xc7, 0x74,
0xf5, 0x6a, 0x9e, 0x25, 0xab, 0xc7, 0x54, 0xf5, 0xfe, 0x34, 0xa1, 0xfc, 0x36, 0x89, 0xfa, 0xb1,
0x20, 0x3b, 0x60, 0x9f, 0xd0, 0x94, 0x32, 0xac, 0xdc, 0xaa, 0xbf, 0xd5, 0x9c, 0xea, 0x58, 0x4d,
0xc5, 0x69, 0x3e, 0x91, 0x84, 0x40, 0xf1, 0x88, 0x2f, 0x4d, 0x95, 0x44, 0x9e, 0xe0, 0x95, 0x92,
0x32, 0xc3, 0xbf, 0xe4, 0x3e, 0x94, 0x39, 0xb6, 0x17, 0x7c, 0x9f, 0x6a, 0xfe, 0xc6, 0x8c, 0x44,
0x75, 0x9e, 0x40, 0x53, 0x48, 0x53, 0x9d, 0x0f, 0xd2, 0xe5, 0xb6, 0x2f, 0xa1, 0xcb, 0x43, 0xd3,
0xfc, 0x0a, 0x53, 0x45, 0x77, 0x37, 0xd1, 0x7d, 0x73, 0x86, 0xae, 0x03, 0x11, 0x14, 0x24, 0xf2,
0x00, 0x1c, 0xd6, 0x29, 0x14, 0xd7, 0x71, 0x81, 0xc5, 0x8a, 0x2a, 0xd3, 0xbf, 0xea, 0x77, 0xc1,
0x56, 0x0f, 0x52, 0x01, 0x2b, 0x38, 0xd8, 0x5f, 0x5b, 0x22, 0x0e, 0xd8, 0x9f, 0x05, 0x07, 0x07,
0x47, 0x6b, 0x06, 0xa9, 0x42, 0x69, 0xef, 0xc5, 0x9b, 0x83, 0x35, 0xb3, 0xfe, 0x8b, 0x09, 0xa5,
0x97, 0xe1, 0x80, 0x93, 0x4f, 0xa1, 0x96, 0x4d, 0xf5, 0x36, 0x03, 0x17, 0xf1, 0x66, 0x16, 0x91,
0xbc, 0xe6, 0xcb, 0xa2, 0xdb, 0x1d, 0xe4, 0x82, 0x8d, 0x02, 0x27, 0x1b, 0x77, 0xbf, 0x43, 0x58,
0xc9, 0x30, 0xbe, 0xc5, 0x49, 0x98, 0xe8, 0x51, 0x5f, 0xe0, 0x21, 0x73, 0xad, 0x8e, 0x42, 0xb9,
0xd4, 0xb2, 0xc9, 0xcc, 0xf6, 0x27, 0xb0, 0x3a, 0xbb, 0x08, 0x59, 0x03, 0xeb, 0xdb, 0x78, 0x84,
0xe5, 0xb6, 0x02, 0xf9, 0x93, 0x6c, 0x82, 0x7d, 0x16, 0xa6, 0xc3, 0x18, 0x5f, 0x53, 0x27, 0x50,
0x83, 0x87, 0xe6, 0x47, 0xc6, 0xf6, 0x31, 0xac, 0xcd, 0xdb, 0x4f, 0xeb, 0xab, 0x4a, 0xff, 0xdf,
0x69, 0xfd, 0x25, 0xd5, 0x9a, 0x98, 0xd6, 0xff, 0x32, 0x60, 0xf9, 0x25, 0xef, 0xbf, 0x4d, 0xc4,
0xe9, 0xab, 0x3c, 0xa6, 0x3d, 0x72, 0x03, 0x6c, 0x91, 0x88, 0x34, 0x46, 0x4f, 0xe7, 0xe9, 0x52,
0xa0, 0x86, 0xc4, 0x85, 0x32, 0x0f, 0xd3, 0x90, 0x8d, 0xd0, 0xd8, 0x7a, 0xba, 0x14, 0xe8, 0x31,
0xd9, 0x86, 0xca, 0x13, 0x3a, 0x94, 0xdb, 0xc1, 0x1e, 0x22, 0x35, 0xc5, 0x04, 0xb9, 0x03, 0xcb,
0xa7, 0x34, 0x8b, 0x3b, 0x61, 0x14, 0xb1, 0x98, 0x73, 0x6c, 0x27, 0x92, 0x50, 0x93, 0xb3, 0x8f,
0xd5, 0x24, 0xf9, 0x1c, 0xd6, 0x33, 0xde, 0xef, 0xbc, 0x4b, 0xc4, 0x69, 0x87, 0xc5, 0xdf, 0x0d,
0x13, 0x16, 0x47, 0xd8, 0x62, 0x6a, 0xfe, 0xad, 0xd9, 0x23, 0x56, 0x1b, 0x0d, 0x34, 0xe7, 0xe9,
0x52, 0x70, 0x2d, 0x9b, 0x9d, 0xda, 0xab, 0x80, 0x3d, 0xcc, 0x13, 0x9a, 0xd7, 0xff, 0x0d, 0xa5,
0x20, 0x0e, 0xd3, 0xc9, 0x79, 0x1a, 0xaa, 0x39, 0xe1, 0xe0, 0x5e, 0xb5, 0x1a, 0xad, 0x9d, 0x9f,
0x9f, 0x9f, 0x9b, 0xf5, 0x9f, 0x0c, 0xb9, 0x7d, 0x79, 0x2c, 0xef, 0xc9, 0x2d, 0x70, 0x92, 0x2c,
0xec, 0x27, 0xb9, 0x7c, 0x4c, 0xc5, 0x9f, 0x4c, 0x4c, 0x34, 0xfe, 0x11, 0xac, 0xb2, 0x38, 0x4c,
0x3b, 0xf1, 0x7b, 0x11, 0xe7, 0x3c, 0xa1, 0x39, 0x59, 0x9f, 0xcb, 0x6c, 0x98, 0xba, 0xdf, 0x2f,
0x88, 0xbf, 0x5e, 0x28, 0x58, 0x91, 0xf2, 0x83, 0x42, 0x5d, 0xff, 0xc3, 0x06, 0x78, 0x9e, 0xd3,
0x77, 0xf9, 0xeb, 0xd1, 0x20, 0xe6, 0xe4, 0x5f, 0x60, 0x86, 0x39, 0xde, 0x39, 0x52, 0xaf, 0xbe,
0x16, 0x9a, 0xc5, 0xd7, 0x42, 0xf3, 0x71, 0x3e, 0x0a, 0xcc, 0x30, 0x27, 0xf7, 0xc1, 0x8a, 0x86,
0xaa, 0x53, 0xd4, 0xfc, 0xad, 0x0b, 0xb4, 0x7d, 0xfd, 0xcd, 0x12, 0x48, 0x16, 0xf9, 0x0f, 0x98,
0x5c, 0xe0, 0x15, 0x58, 0xf3, 0x6f, 0x5e, 0xe0, 0x1e, 0xe3, 0xf7, 0x4b, 0x60, 0x72, 0x41, 0xee,
0x81, 0x29, 0xb8, 0xce, 0xce, 0xf6, 0x05, 0xe2, 0xeb, 0xe2, 0x53, 0x26, 0x30, 0x05, 0x97, 0xdc,
0xf4, 0x0c, 0xaf, 0xbf, 0x45, 0xdc, 0x17, 0x09, 0x17, 0x5f, 0xca, 0xc3, 0x0e, 0xcc, 0xf4, 0x8c,
0x34, 0xc0, 0x3a, 0x0b, 0x53, 0xbc, 0x0e, 0x6b, 0xfe, 0x8d, 0x0b, 0x64, 0x45, 0x94, 0x14, 0xd2,
0x04, 0x2b, 0xea, 0xa6, 0x18, 0x25, 0x59, 0xff, 0x0b, 0xcf, 0x85, 0x8d, 0x56, 0xf3, 0xa3, 0x6e,
0x4a, 0xfe, 0x07, 0x56, 0x2f, 0x15, 0x98, 0xac, 0x9a, 0xff, 0x8f, 0x0b, 0x7c, 0x6c, 0xd9, 0x9a,
0xde, 0x4b, 0x85, 0xa4, 0x27, 0x78, 0x43, 0x2c, 0xa6, 0xe3, 0xeb, 0xa9, 0xe9, 0x49, 0xbb, 0x25,
0x77, 0x33, 0x6c, 0xb7, 0xf0, 0x66, 0x5b, 0xb4, 0x9b, 0x37, 0xd3, 0xfc, 0x61, 0xbb, 0x85, 0xf6,
0xbb, 0x3e, 0x7e, 0x04, 0x5d, 0x62, 0xbf, 0xeb, 0x17, 0xf6, 0xbb, 0x3e, 0xda, 0xef, 0xfa, 0xf8,
0x55, 0x74, 0x99, 0xfd, 0x98, 0x3f, 0x44, 0x7e, 0x09, 0xaf, 0x51, 0xe7, 0x92, 0x43, 0x97, 0xfd,
0x41, 0xd1, 0x91, 0x27, 0xfd, 0x65, 0xcf, 0x83, 0x4b, 0xfc, 0xd5, 0xd5, 0xa4, 0xfd, 0xb9, 0x60,
0xe4, 0x01, 0xd8, 0xc5, 0x15, 0xb5, 0xf8, 0x01, 0xf0, 0xca, 0x52, 0x02, 0xc5, 0xac, 0xdf, 0x81,
0x6b, 0x73, 0xef, 0xa5, 0xec, 0x4a, 0xaa, 0xd3, 0x9a, 0x0d, 0x07, 0x7d, 0xeb, 0xbf, 0x9b, 0x70,
0x53, 0xb3, 0x9e, 0xe5, 0x51, 0xc2, 0xe2, 0x13, 0x31, 0x66, 0xff, 0x1f, 0x4a, 0x7c, 0xd8, 0xcd,
0x74, 0x92, 0xaf, 0x7c, 0xe3, 0x03, 0x64, 0x92, 0x57, 0xe0, 0x64, 0xe1, 0xa0, 0xd3, 0x4b, 0xe2,
0x34, 0xd2, 0xbd, 0xd8, 0x5f, 0x24, 0x9b, 0x5f, 0x4a, 0xf6, 0xe8, 0x43, 0x29, 0x52, 0xbd, 0xb9,
0x9a, 0xe9, 0x21, 0x79, 0x04, 0x35, 0x9e, 0x26, 0x27, 0xb1, 0xb6, 0xb4, 0xd0, 0xf2, 0xea, 0x9d,
0x00, 0x0a, 0x50, 0xbe, 0xfd, 0x15, 0xac, 0xcc, 0x38, 0x4f, 0xb7, 0x65, 0x47, 0xb5, 0x65, 0x7f,
0xb6, 0x2d, 0x5f, 0xed, 0x3d, 0xd5, 0x9f, 0xef, 0xc1, 0xe6, 0x1c, 0x8a, 0x15, 0x20, 0x04, 0x4a,
0xdd, 0x91, 0xe0, 0x78, 0xc6, 0xcb, 0x01, 0xfe, 0xae, 0xef, 0x03, 0x99, 0xe3, 0xbe, 0x7d, 0xfe,
0xba, 0x88, 0x80, 0x24, 0x7e, 0x48, 0x04, 0x1e, 0xde, 0x85, 0x52, 0x1e, 0x66, 0xf1, 0xa2, 0x96,
0xf6, 0x03, 0x3e, 0x0f, 0xc2, 0x0f, 0x9f, 0x40, 0x29, 0x7e, 0x2f, 0xb2, 0x45, 0xb4, 0x1f, 0x3f,
0xa4, 0x90, 0x52, 0xbc, 0xf7, 0xe8, 0xeb, 0x8f, 0xfb, 0x89, 0x38, 0x1d, 0x76, 0x9b, 0x27, 0x34,
0xdb, 0xe9, 0xd3, 0x34, 0xcc, 0xfb, 0x93, 0xff, 0x8b, 0x92, 0x5c, 0xc4, 0x2c, 0x0f, 0x53, 0xfc,
0x27, 0x0e, 0x67, 0xf9, 0xce, 0xf4, 0x3f, 0x77, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xba, 0x6b,
0x0b, 0xa0, 0xeb, 0x0d, 0x00, 0x00,
}

Просмотреть файл

@ -1,37 +1,10 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Copyright 2015 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.
syntax = "proto2";
option go_package = "github.com/golang/protobuf/jsonpb/jsonpb_test_proto;jsonpb";
option go_package = "github.com/golang/protobuf/internal/testprotos/jsonpb_proto";
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
@ -39,7 +12,7 @@ import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
package jsonpb;
package jsonpb_test;
// Test message for holding primitive types.
message Simple {

Просмотреть файл

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: jsonpb_test_proto/more_test_objects.proto
// source: jsonpb_proto/test3.proto
package jsonpb
package jsonpb_proto
import (
fmt "fmt"
@ -45,7 +45,7 @@ func (x Numeral) String() string {
}
func (Numeral) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{0}
return fileDescriptor_813baf511b225405, []int{0}
}
type Simple3 struct {
@ -59,7 +59,7 @@ func (m *Simple3) Reset() { *m = Simple3{} }
func (m *Simple3) String() string { return proto.CompactTextString(m) }
func (*Simple3) ProtoMessage() {}
func (*Simple3) Descriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{0}
return fileDescriptor_813baf511b225405, []int{0}
}
func (m *Simple3) XXX_Unmarshal(b []byte) error {
@ -98,7 +98,7 @@ func (m *SimpleSlice3) Reset() { *m = SimpleSlice3{} }
func (m *SimpleSlice3) String() string { return proto.CompactTextString(m) }
func (*SimpleSlice3) ProtoMessage() {}
func (*SimpleSlice3) Descriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{1}
return fileDescriptor_813baf511b225405, []int{1}
}
func (m *SimpleSlice3) XXX_Unmarshal(b []byte) error {
@ -137,7 +137,7 @@ func (m *SimpleMap3) Reset() { *m = SimpleMap3{} }
func (m *SimpleMap3) String() string { return proto.CompactTextString(m) }
func (*SimpleMap3) ProtoMessage() {}
func (*SimpleMap3) Descriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{2}
return fileDescriptor_813baf511b225405, []int{2}
}
func (m *SimpleMap3) XXX_Unmarshal(b []byte) error {
@ -176,7 +176,7 @@ func (m *SimpleNull3) Reset() { *m = SimpleNull3{} }
func (m *SimpleNull3) String() string { return proto.CompactTextString(m) }
func (*SimpleNull3) ProtoMessage() {}
func (*SimpleNull3) Descriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{3}
return fileDescriptor_813baf511b225405, []int{3}
}
func (m *SimpleNull3) XXX_Unmarshal(b []byte) error {
@ -210,7 +210,7 @@ type Mappy struct {
Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy,proto3" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy,proto3" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly,proto3" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy,proto3" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=jsonpb.Numeral"`
Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy,proto3" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=jsonpb_test.Numeral"`
S32Booly map[int32]bool `protobuf:"bytes,7,rep,name=s32booly,proto3" json:"s32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
S64Booly map[int64]bool `protobuf:"bytes,8,rep,name=s64booly,proto3" json:"s64booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
U32Booly map[uint32]bool `protobuf:"bytes,9,rep,name=u32booly,proto3" json:"u32booly,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
@ -224,7 +224,7 @@ func (m *Mappy) Reset() { *m = Mappy{} }
func (m *Mappy) String() string { return proto.CompactTextString(m) }
func (*Mappy) ProtoMessage() {}
func (*Mappy) Descriptor() ([]byte, []int) {
return fileDescriptor_59defc22c5ce96e7, []int{4}
return fileDescriptor_813baf511b225405, []int{4}
}
func (m *Mappy) XXX_Unmarshal(b []byte) error {
@ -316,65 +316,63 @@ func (m *Mappy) GetU64Booly() map[uint64]bool {
}
func init() {
proto.RegisterEnum("jsonpb.Numeral", Numeral_name, Numeral_value)
proto.RegisterType((*Simple3)(nil), "jsonpb.Simple3")
proto.RegisterType((*SimpleSlice3)(nil), "jsonpb.SimpleSlice3")
proto.RegisterType((*SimpleMap3)(nil), "jsonpb.SimpleMap3")
proto.RegisterMapType((map[string]string)(nil), "jsonpb.SimpleMap3.StringyEntry")
proto.RegisterType((*SimpleNull3)(nil), "jsonpb.SimpleNull3")
proto.RegisterType((*Mappy)(nil), "jsonpb.Mappy")
proto.RegisterMapType((map[bool]bool)(nil), "jsonpb.Mappy.BoolyEntry")
proto.RegisterMapType((map[int64]string)(nil), "jsonpb.Mappy.BuggyEntry")
proto.RegisterMapType((map[string]Numeral)(nil), "jsonpb.Mappy.EnumyEntry")
proto.RegisterMapType((map[int64]int32)(nil), "jsonpb.Mappy.NummyEntry")
proto.RegisterMapType((map[int32]*Simple3)(nil), "jsonpb.Mappy.ObjjyEntry")
proto.RegisterMapType((map[int32]bool)(nil), "jsonpb.Mappy.S32boolyEntry")
proto.RegisterMapType((map[int64]bool)(nil), "jsonpb.Mappy.S64boolyEntry")
proto.RegisterMapType((map[string]string)(nil), "jsonpb.Mappy.StrryEntry")
proto.RegisterMapType((map[uint32]bool)(nil), "jsonpb.Mappy.U32boolyEntry")
proto.RegisterMapType((map[uint64]bool)(nil), "jsonpb.Mappy.U64boolyEntry")
proto.RegisterEnum("jsonpb_test.Numeral", Numeral_name, Numeral_value)
proto.RegisterType((*Simple3)(nil), "jsonpb_test.Simple3")
proto.RegisterType((*SimpleSlice3)(nil), "jsonpb_test.SimpleSlice3")
proto.RegisterType((*SimpleMap3)(nil), "jsonpb_test.SimpleMap3")
proto.RegisterMapType((map[string]string)(nil), "jsonpb_test.SimpleMap3.StringyEntry")
proto.RegisterType((*SimpleNull3)(nil), "jsonpb_test.SimpleNull3")
proto.RegisterType((*Mappy)(nil), "jsonpb_test.Mappy")
proto.RegisterMapType((map[bool]bool)(nil), "jsonpb_test.Mappy.BoolyEntry")
proto.RegisterMapType((map[int64]string)(nil), "jsonpb_test.Mappy.BuggyEntry")
proto.RegisterMapType((map[string]Numeral)(nil), "jsonpb_test.Mappy.EnumyEntry")
proto.RegisterMapType((map[int64]int32)(nil), "jsonpb_test.Mappy.NummyEntry")
proto.RegisterMapType((map[int32]*Simple3)(nil), "jsonpb_test.Mappy.ObjjyEntry")
proto.RegisterMapType((map[int32]bool)(nil), "jsonpb_test.Mappy.S32boolyEntry")
proto.RegisterMapType((map[int64]bool)(nil), "jsonpb_test.Mappy.S64boolyEntry")
proto.RegisterMapType((map[string]string)(nil), "jsonpb_test.Mappy.StrryEntry")
proto.RegisterMapType((map[uint32]bool)(nil), "jsonpb_test.Mappy.U32boolyEntry")
proto.RegisterMapType((map[uint64]bool)(nil), "jsonpb_test.Mappy.U64boolyEntry")
}
func init() {
proto.RegisterFile("jsonpb_test_proto/more_test_objects.proto", fileDescriptor_59defc22c5ce96e7)
}
func init() { proto.RegisterFile("jsonpb_proto/test3.proto", fileDescriptor_813baf511b225405) }
var fileDescriptor_59defc22c5ce96e7 = []byte{
// 567 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x95, 0xdf, 0x8b, 0xd3, 0x4e,
0x14, 0xc5, 0xbf, 0x69, 0x37, 0x69, 0x7b, 0xbb, 0xfb, 0xb5, 0x0c, 0x22, 0xa1, 0xfb, 0xe0, 0x12,
0x50, 0x57, 0xc1, 0x04, 0x1a, 0x59, 0xd7, 0xae, 0x2f, 0xad, 0xec, 0xc3, 0x22, 0x4d, 0x21, 0xa5,
0x08, 0xbe, 0x2c, 0x49, 0x8d, 0xb1, 0x35, 0xc9, 0x84, 0x24, 0x23, 0xe4, 0xd9, 0xbf, 0x5b, 0x90,
0xf9, 0x91, 0x4d, 0x52, 0xa7, 0x54, 0xdf, 0xe6, 0xce, 0xf9, 0x9c, 0xdc, 0x33, 0x33, 0x97, 0x16,
0x5e, 0xee, 0x72, 0x9c, 0xa4, 0xfe, 0x7d, 0x11, 0xe4, 0xc5, 0x7d, 0x9a, 0xe1, 0x02, 0x5b, 0x31,
0xce, 0x02, 0x5e, 0x63, 0x7f, 0x17, 0x6c, 0x8a, 0xdc, 0x64, 0xfb, 0x48, 0xe3, 0xa8, 0x71, 0x0e,
0xbd, 0xd5, 0x36, 0x4e, 0xa3, 0xc0, 0x46, 0x23, 0xe8, 0x7e, 0x21, 0xbe, 0xae, 0x5c, 0x28, 0x97,
0x8a, 0x4b, 0x97, 0xc6, 0x73, 0x38, 0xe5, 0xe2, 0x2a, 0xda, 0x6e, 0x02, 0x1b, 0x3d, 0x01, 0x2d,
0xa7, 0xab, 0x5c, 0x57, 0x2e, 0xba, 0x97, 0x03, 0x57, 0x54, 0xc6, 0x4f, 0x05, 0x80, 0x83, 0x0b,
0x2f, 0xb5, 0xd1, 0x3b, 0xe8, 0xe5, 0x45, 0xb6, 0x4d, 0xc2, 0x92, 0x71, 0xc3, 0xc9, 0x53, 0x93,
0x77, 0x33, 0x6b, 0xc8, 0x5c, 0x71, 0xe2, 0x36, 0x29, 0xb2, 0xd2, 0xad, 0xf8, 0xf1, 0x14, 0x4e,
0x9b, 0x02, 0xcd, 0xf4, 0x3d, 0x28, 0x59, 0xa6, 0x81, 0x4b, 0x97, 0xe8, 0x31, 0xa8, 0x3f, 0xbc,
0x88, 0x04, 0x7a, 0x87, 0xed, 0xf1, 0x62, 0xda, 0xb9, 0x56, 0x8c, 0x2b, 0x18, 0xf2, 0xef, 0x3b,
0x24, 0x8a, 0x6c, 0xf4, 0x02, 0xb4, 0x9c, 0x95, 0xcc, 0x3d, 0x9c, 0x3c, 0x6a, 0x87, 0xb0, 0x5d,
0x21, 0x1b, 0xbf, 0xfa, 0xa0, 0x2e, 0xbc, 0x34, 0x2d, 0x91, 0x09, 0x6a, 0x42, 0xe2, 0xb8, 0x8a,
0xad, 0x57, 0x0e, 0xa6, 0x9a, 0x0e, 0x95, 0x78, 0x5e, 0x8e, 0x51, 0x3e, 0x2f, 0xb2, 0xac, 0xd4,
0x3b, 0x32, 0x7e, 0x45, 0x25, 0xc1, 0x33, 0x8c, 0xf2, 0xd8, 0xdf, 0xed, 0x4a, 0xbd, 0x2b, 0xe3,
0x97, 0x54, 0x12, 0x3c, 0xc3, 0x28, 0xef, 0x93, 0x30, 0x2c, 0xf5, 0x13, 0x19, 0x3f, 0xa7, 0x92,
0xe0, 0x19, 0xc6, 0x78, 0x8c, 0xa3, 0x52, 0x57, 0xa5, 0x3c, 0x95, 0x2a, 0x9e, 0xae, 0x29, 0x1f,
0x24, 0x24, 0x2e, 0x75, 0x4d, 0xc6, 0xdf, 0x52, 0x49, 0xf0, 0x0c, 0x43, 0x6f, 0xa1, 0x9f, 0xdb,
0x13, 0xde, 0xa2, 0xc7, 0x2c, 0xe7, 0x7b, 0x47, 0x16, 0x2a, 0x77, 0x3d, 0xc0, 0xcc, 0x78, 0xf5,
0x86, 0x1b, 0xfb, 0x52, 0xa3, 0x50, 0x2b, 0xa3, 0x28, 0xa9, 0x91, 0x54, 0x1d, 0x07, 0x32, 0xe3,
0xba, 0xdd, 0x91, 0x34, 0x3a, 0x92, 0xaa, 0x23, 0x48, 0x8d, 0xed, 0x8e, 0x15, 0x3c, 0xbe, 0x06,
0xa8, 0x1f, 0xba, 0x39, 0x7f, 0x5d, 0xc9, 0xfc, 0xa9, 0x8d, 0xf9, 0xa3, 0xce, 0xfa, 0xc9, 0xff,
0x65, 0x72, 0xc7, 0x77, 0x00, 0xf5, 0xe3, 0x37, 0x9d, 0x2a, 0x77, 0x3e, 0x6b, 0x3a, 0x25, 0x93,
0xdc, 0x0e, 0x51, 0xcf, 0xc5, 0xb1, 0xf8, 0x83, 0x7d, 0xe7, 0xc3, 0x85, 0x34, 0x9d, 0x7d, 0x89,
0xb3, 0xbf, 0x17, 0xbf, 0x9e, 0x15, 0xc9, 0xc1, 0x5b, 0xf1, 0xff, 0xaf, 0xe3, 0x3b, 0x24, 0x0e,
0x32, 0x2f, 0x6a, 0x7e, 0xea, 0x06, 0xce, 0x5a, 0x33, 0x24, 0xb9, 0x8c, 0xc3, 0x39, 0xa8, 0xb9,
0xf9, 0xaa, 0xc7, 0x8e, 0xbf, 0x6f, 0x5e, 0x1f, 0xea, 0x7c, 0xf6, 0x37, 0xe6, 0x43, 0x9d, 0x4f,
0x8e, 0x98, 0x5f, 0xbd, 0x86, 0x9e, 0xb8, 0x09, 0x34, 0x84, 0xde, 0xda, 0xf9, 0xe8, 0x2c, 0x3f,
0x39, 0xa3, 0xff, 0x10, 0x80, 0x36, 0x73, 0x67, 0xf3, 0xbb, 0x0f, 0x23, 0x05, 0x0d, 0x40, 0x75,
0x97, 0x8b, 0x99, 0x33, 0xea, 0xcc, 0xdf, 0x7f, 0x9e, 0x86, 0xdb, 0xe2, 0x1b, 0xf1, 0xcd, 0x0d,
0x8e, 0xad, 0x10, 0x47, 0x5e, 0x12, 0x5a, 0xec, 0x47, 0xdd, 0x27, 0x5f, 0x2d, 0x7e, 0xb5, 0xd6,
0x1f, 0x7f, 0x04, 0x37, 0x7c, 0xc7, 0xd7, 0x58, 0x65, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xd5,
0x45, 0xc4, 0x18, 0x2b, 0x06, 0x00, 0x00,
var fileDescriptor_813baf511b225405 = []byte{
// 563 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x95, 0xdd, 0x8a, 0xd3, 0x40,
0x14, 0xc7, 0x4d, 0xbb, 0x69, 0x9b, 0xd3, 0x5d, 0x29, 0xc3, 0x22, 0xa1, 0x22, 0x94, 0x22, 0xb2,
0x2c, 0x9a, 0x40, 0x23, 0xb2, 0x6c, 0x55, 0x68, 0x65, 0x2f, 0x44, 0x9a, 0x42, 0x4a, 0x11, 0xbc,
0x91, 0x64, 0x8d, 0x31, 0x35, 0x5f, 0x24, 0x19, 0x21, 0x6f, 0xe0, 0x2b, 0xf9, 0x76, 0x32, 0x1f,
0xd9, 0x4c, 0x4a, 0x86, 0xea, 0xd5, 0x9e, 0x99, 0xf3, 0xff, 0xe5, 0x7c, 0xec, 0xbf, 0x0c, 0xe8,
0x87, 0x22, 0x4d, 0x32, 0xef, 0x6b, 0x96, 0xa7, 0x65, 0x6a, 0x96, 0x7e, 0x51, 0x5a, 0x06, 0x8d,
0xd1, 0x98, 0x67, 0xc8, 0xdd, 0xfc, 0x29, 0x0c, 0x77, 0x61, 0x9c, 0x45, 0xbe, 0x85, 0x26, 0xd0,
0xff, 0x86, 0x3d, 0x5d, 0x99, 0x29, 0x57, 0x8a, 0x43, 0xc2, 0xf9, 0x0b, 0x38, 0x67, 0xc9, 0x5d,
0x14, 0xde, 0xfb, 0x16, 0x7a, 0x02, 0x83, 0x82, 0x44, 0x85, 0xae, 0xcc, 0xfa, 0x57, 0x9a, 0xc3,
0x4f, 0xf3, 0xdf, 0x0a, 0x00, 0x13, 0x6e, 0xdc, 0xcc, 0x42, 0xef, 0x61, 0x58, 0x94, 0x79, 0x98,
0x04, 0x15, 0xd5, 0x8d, 0x17, 0xcf, 0x0d, 0xa1, 0xa4, 0xd1, 0x28, 0x8d, 0x1d, 0x93, 0xdd, 0x25,
0x65, 0x5e, 0x39, 0x35, 0x34, 0xbd, 0x85, 0x73, 0x31, 0x41, 0x1a, 0xfb, 0xe9, 0x57, 0xb4, 0x31,
0xcd, 0x21, 0x21, 0xba, 0x04, 0xf5, 0x97, 0x1b, 0x61, 0x5f, 0xef, 0xd1, 0x3b, 0x76, 0xb8, 0xed,
0xdd, 0x28, 0xf3, 0x25, 0x8c, 0xd9, 0xf7, 0x6d, 0x1c, 0x45, 0x16, 0x7a, 0x09, 0x83, 0x82, 0x1e,
0x29, 0x3d, 0x5e, 0x5c, 0x76, 0x74, 0x62, 0x39, 0x5c, 0x33, 0xff, 0xa3, 0x81, 0xba, 0x71, 0xb3,
0xac, 0x42, 0x16, 0xa8, 0x09, 0x8e, 0xe3, 0x7a, 0x80, 0x67, 0x2d, 0x8c, 0x4a, 0x0c, 0x9b, 0xe4,
0x59, 0xe7, 0x4c, 0x4b, 0xa0, 0xa2, 0xcc, 0xf3, 0x4a, 0xef, 0x49, 0xa1, 0x1d, 0xc9, 0x73, 0x88,
0x6a, 0x09, 0x94, 0x7a, 0x87, 0x43, 0xa5, 0xf7, 0xa5, 0xd0, 0x96, 0xe4, 0x39, 0x44, 0xb5, 0x04,
0xf2, 0x70, 0x10, 0x54, 0xfa, 0x99, 0x14, 0x5a, 0x93, 0x3c, 0x87, 0xa8, 0x96, 0x42, 0x69, 0x1a,
0x55, 0xba, 0x2a, 0x87, 0x48, 0xbe, 0x86, 0x48, 0x4c, 0x20, 0x3f, 0xc1, 0x71, 0xa5, 0x0f, 0xa4,
0xd0, 0x1d, 0xc9, 0x73, 0x88, 0x6a, 0xd1, 0x5b, 0x18, 0x15, 0xd6, 0x82, 0x15, 0x1b, 0x52, 0x6e,
0xd6, 0xb5, 0x0b, 0x2e, 0x61, 0xe8, 0x03, 0x41, 0xe9, 0x37, 0xaf, 0x19, 0x3d, 0x92, 0xd3, 0x5c,
0x52, 0xd3, 0xfc, 0x48, 0x68, 0x5c, 0xd7, 0xd6, 0xa4, 0xf4, 0xbe, 0x5d, 0x1b, 0x0b, 0xb5, 0x71,
0x5d, 0x1b, 0xe4, 0x74, 0xbb, 0x76, 0x4d, 0x4c, 0x6f, 0x00, 0x1a, 0x57, 0x88, 0xb6, 0xed, 0x77,
0xd8, 0x56, 0x15, 0x6c, 0x4b, 0xc8, 0xc6, 0x1a, 0xff, 0x63, 0xf8, 0xa9, 0x0d, 0xd0, 0xf8, 0x43,
0x24, 0x55, 0x46, 0x5e, 0x8b, 0xa4, 0xec, 0x07, 0xd0, 0xee, 0xa4, 0xb1, 0xce, 0xa9, 0x19, 0xb4,
0x63, 0xf2, 0x61, 0x2b, 0x22, 0x39, 0xea, 0x20, 0x47, 0x47, 0x33, 0x34, 0x26, 0xea, 0x98, 0xbe,
0x35, 0xc3, 0xe3, 0xa3, 0x19, 0x6c, 0x1c, 0xfb, 0xb9, 0x1b, 0x89, 0xdf, 0x5b, 0xc2, 0x45, 0xcb,
0x5c, 0x1d, 0x6b, 0x91, 0x37, 0x43, 0x60, 0xf1, 0xff, 0x7b, 0x6a, 0x07, 0xc7, 0xf0, 0x5e, 0x56,
0xf9, 0xe2, 0x5f, 0x60, 0x59, 0xe5, 0xb3, 0x13, 0xf0, 0xf5, 0x2b, 0x18, 0xf2, 0x4d, 0xa0, 0x31,
0x0c, 0xf7, 0xf6, 0x27, 0x7b, 0xfb, 0xd9, 0x9e, 0x3c, 0x42, 0x00, 0x83, 0x95, 0xb3, 0x5a, 0x7f,
0xfc, 0x30, 0x51, 0x90, 0x06, 0xaa, 0xb3, 0xdd, 0xac, 0xec, 0x49, 0x6f, 0xfd, 0xee, 0xcb, 0x32,
0x08, 0xcb, 0x1f, 0xd8, 0x33, 0xee, 0xd3, 0xd8, 0x0c, 0xd2, 0xc8, 0x4d, 0x02, 0x93, 0xbe, 0x0f,
0x1e, 0xfe, 0x6e, 0x86, 0x49, 0xe9, 0xe7, 0x89, 0x1b, 0xd1, 0x77, 0x83, 0xde, 0x16, 0xa6, 0xf8,
0x9e, 0x78, 0x03, 0xfa, 0xc7, 0xfa, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x7c, 0xda, 0x44, 0x24, 0x66,
0x06, 0x00, 0x00,
}

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright 2015 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.
syntax = "proto3";
option go_package = "github.com/golang/protobuf/internal/testprotos/jsonpb_proto";
package jsonpb_test;
message Simple3 {
double dub = 1;
}
message SimpleSlice3 {
repeated string slices = 1;
}
message SimpleMap3 {
map<string,string> stringy = 1;
}
message SimpleNull3 {
Simple3 simple = 1;
}
enum Numeral {
UNKNOWN = 0;
ARABIC = 1;
ROMAN = 2;
}
message Mappy {
map<int64, int32> nummy = 1;
map<string, string> strry = 2;
map<int32, Simple3> objjy = 3;
map<int64, string> buggy = 4;
map<bool, bool> booly = 5;
map<string, Numeral> enumy = 6;
map<int32, bool> s32booly = 7;
map<int64, bool> s64booly = 8;
map<uint32, bool> u32booly = 9;
map<uint64, bool> u64booly = 10;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,41 +1,14 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Copyright 2010 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.
// A feature-rich test file for the protocol compiler and libraries.
syntax = "proto2";
option go_package = "github.com/golang/protobuf/proto/test_proto";
option go_package = "github.com/golang/protobuf/internal/testprotos/proto2_proto";
package test_proto;
package proto2_test;
enum FOO { FOO1 = 1; };
@ -361,67 +334,9 @@ extend DefaultsMessage {
optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE];
}
message MyMessageSet {
option message_set_wire_format = true;
extensions 100 to max;
}
message Empty {
}
extend MyMessageSet {
optional Empty x201 = 201;
optional Empty x202 = 202;
optional Empty x203 = 203;
optional Empty x204 = 204;
optional Empty x205 = 205;
optional Empty x206 = 206;
optional Empty x207 = 207;
optional Empty x208 = 208;
optional Empty x209 = 209;
optional Empty x210 = 210;
optional Empty x211 = 211;
optional Empty x212 = 212;
optional Empty x213 = 213;
optional Empty x214 = 214;
optional Empty x215 = 215;
optional Empty x216 = 216;
optional Empty x217 = 217;
optional Empty x218 = 218;
optional Empty x219 = 219;
optional Empty x220 = 220;
optional Empty x221 = 221;
optional Empty x222 = 222;
optional Empty x223 = 223;
optional Empty x224 = 224;
optional Empty x225 = 225;
optional Empty x226 = 226;
optional Empty x227 = 227;
optional Empty x228 = 228;
optional Empty x229 = 229;
optional Empty x230 = 230;
optional Empty x231 = 231;
optional Empty x232 = 232;
optional Empty x233 = 233;
optional Empty x234 = 234;
optional Empty x235 = 235;
optional Empty x236 = 236;
optional Empty x237 = 237;
optional Empty x238 = 238;
optional Empty x239 = 239;
optional Empty x240 = 240;
optional Empty x241 = 241;
optional Empty x242 = 242;
optional Empty x243 = 243;
optional Empty x244 = 244;
optional Empty x245 = 245;
optional Empty x246 = 246;
optional Empty x247 = 247;
optional Empty x248 = 248;
optional Empty x249 = 249;
optional Empty x250 = 250;
}
message MessageList {
repeated group Message = 1 {
required string name = 2;

Просмотреть файл

@ -1,13 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto3_proto/proto3.proto
// source: proto3_proto/test.proto
package proto3_proto
import (
fmt "fmt"
proto2_proto "github.com/golang/protobuf/internal/testprotos/proto2_proto"
proto "github.com/golang/protobuf/proto"
test_proto "github.com/golang/protobuf/proto/test_proto"
any "github.com/golang/protobuf/ptypes/any"
anypb "google.golang.org/protobuf/types/known/anypb"
math "math"
)
@ -50,39 +50,39 @@ func (x Message_Humour) String() string {
}
func (Message_Humour) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{0, 0}
return fileDescriptor_ff83f0b8d2b92afa, []int{0, 0}
}
type Message struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"`
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm,proto3" json:"height_in_cm,omitempty"`
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount,proto3" json:"result_count,omitempty"`
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman,proto3" json:"true_scotsman,omitempty"`
Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"`
Key []uint64 `protobuf:"varint,5,rep,packed,name=key,proto3" json:"key,omitempty"`
ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey,proto3" json:"short_key,omitempty"`
Nested *Nested `protobuf:"bytes,6,opt,name=nested,proto3" json:"nested,omitempty"`
RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,proto3,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"`
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain,proto3" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Proto2Field *test_proto.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field,proto3" json:"proto2_field,omitempty"`
Proto2Value map[string]*test_proto.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value,proto3" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Anything *any.Any `protobuf:"bytes,14,opt,name=anything,proto3" json:"anything,omitempty"`
ManyThings []*any.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings,proto3" json:"many_things,omitempty"`
Submessage *Message `protobuf:"bytes,17,opt,name=submessage,proto3" json:"submessage,omitempty"`
Children []*Message `protobuf:"bytes,18,rep,name=children,proto3" json:"children,omitempty"`
StringMap map[string]string `protobuf:"bytes,20,rep,name=string_map,json=stringMap,proto3" json:"string_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_test.Message_Humour" json:"hilarity,omitempty"`
HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm,proto3" json:"height_in_cm,omitempty"`
Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount,proto3" json:"result_count,omitempty"`
TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman,proto3" json:"true_scotsman,omitempty"`
Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"`
Key []uint64 `protobuf:"varint,5,rep,packed,name=key,proto3" json:"key,omitempty"`
ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey,proto3" json:"short_key,omitempty"`
Nested *Nested `protobuf:"bytes,6,opt,name=nested,proto3" json:"nested,omitempty"`
RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,proto3,enum=proto3_test.Message_Humour" json:"r_funny,omitempty"`
Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain,proto3" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Proto2Field *proto2_proto.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field,proto3" json:"proto2_field,omitempty"`
Proto2Value map[string]*proto2_proto.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value,proto3" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Anything *anypb.Any `protobuf:"bytes,14,opt,name=anything,proto3" json:"anything,omitempty"`
ManyThings []*anypb.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings,proto3" json:"many_things,omitempty"`
Submessage *Message `protobuf:"bytes,17,opt,name=submessage,proto3" json:"submessage,omitempty"`
Children []*Message `protobuf:"bytes,18,rep,name=children,proto3" json:"children,omitempty"`
StringMap map[string]string `protobuf:"bytes,20,rep,name=string_map,json=stringMap,proto3" json:"string_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{0}
return fileDescriptor_ff83f0b8d2b92afa, []int{0}
}
func (m *Message) XXX_Unmarshal(b []byte) error {
@ -187,28 +187,28 @@ func (m *Message) GetTerrain() map[string]*Nested {
return nil
}
func (m *Message) GetProto2Field() *test_proto.SubDefaults {
func (m *Message) GetProto2Field() *proto2_proto.SubDefaults {
if m != nil {
return m.Proto2Field
}
return nil
}
func (m *Message) GetProto2Value() map[string]*test_proto.SubDefaults {
func (m *Message) GetProto2Value() map[string]*proto2_proto.SubDefaults {
if m != nil {
return m.Proto2Value
}
return nil
}
func (m *Message) GetAnything() *any.Any {
func (m *Message) GetAnything() *anypb.Any {
if m != nil {
return m.Anything
}
return nil
}
func (m *Message) GetManyThings() []*any.Any {
func (m *Message) GetManyThings() []*anypb.Any {
if m != nil {
return m.ManyThings
}
@ -248,7 +248,7 @@ func (m *Nested) Reset() { *m = Nested{} }
func (m *Nested) String() string { return proto.CompactTextString(m) }
func (*Nested) ProtoMessage() {}
func (*Nested) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{1}
return fileDescriptor_ff83f0b8d2b92afa, []int{1}
}
func (m *Nested) XXX_Unmarshal(b []byte) error {
@ -294,7 +294,7 @@ func (m *MessageWithMap) Reset() { *m = MessageWithMap{} }
func (m *MessageWithMap) String() string { return proto.CompactTextString(m) }
func (*MessageWithMap) ProtoMessage() {}
func (*MessageWithMap) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{2}
return fileDescriptor_ff83f0b8d2b92afa, []int{2}
}
func (m *MessageWithMap) XXX_Unmarshal(b []byte) error {
@ -333,7 +333,7 @@ func (m *IntMap) Reset() { *m = IntMap{} }
func (m *IntMap) String() string { return proto.CompactTextString(m) }
func (*IntMap) ProtoMessage() {}
func (*IntMap) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{3}
return fileDescriptor_ff83f0b8d2b92afa, []int{3}
}
func (m *IntMap) XXX_Unmarshal(b []byte) error {
@ -372,7 +372,7 @@ func (m *IntMaps) Reset() { *m = IntMaps{} }
func (m *IntMaps) String() string { return proto.CompactTextString(m) }
func (*IntMaps) ProtoMessage() {}
func (*IntMaps) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{4}
return fileDescriptor_ff83f0b8d2b92afa, []int{4}
}
func (m *IntMaps) XXX_Unmarshal(b []byte) error {
@ -417,7 +417,7 @@ func (m *TestUTF8) Reset() { *m = TestUTF8{} }
func (m *TestUTF8) String() string { return proto.CompactTextString(m) }
func (*TestUTF8) ProtoMessage() {}
func (*TestUTF8) Descriptor() ([]byte, []int) {
return fileDescriptor_1c50d9b824d4ac38, []int{5}
return fileDescriptor_ff83f0b8d2b92afa, []int{5}
}
func (m *TestUTF8) XXX_Unmarshal(b []byte) error {
@ -498,82 +498,82 @@ func (*TestUTF8) XXX_OneofWrappers() []interface{} {
}
func init() {
proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value)
proto.RegisterType((*Message)(nil), "proto3_proto.Message")
proto.RegisterMapType((map[string]*test_proto.SubDefaults)(nil), "proto3_proto.Message.Proto2ValueEntry")
proto.RegisterMapType((map[string]string)(nil), "proto3_proto.Message.StringMapEntry")
proto.RegisterMapType((map[string]*Nested)(nil), "proto3_proto.Message.TerrainEntry")
proto.RegisterType((*Nested)(nil), "proto3_proto.Nested")
proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap")
proto.RegisterMapType((map[bool][]byte)(nil), "proto3_proto.MessageWithMap.ByteMappingEntry")
proto.RegisterType((*IntMap)(nil), "proto3_proto.IntMap")
proto.RegisterMapType((map[int32]int32)(nil), "proto3_proto.IntMap.RttEntry")
proto.RegisterType((*IntMaps)(nil), "proto3_proto.IntMaps")
proto.RegisterType((*TestUTF8)(nil), "proto3_proto.TestUTF8")
proto.RegisterMapType((map[string]int64)(nil), "proto3_proto.TestUTF8.MapKeyEntry")
proto.RegisterMapType((map[int64]string)(nil), "proto3_proto.TestUTF8.MapValueEntry")
proto.RegisterEnum("proto3_test.Message_Humour", Message_Humour_name, Message_Humour_value)
proto.RegisterType((*Message)(nil), "proto3_test.Message")
proto.RegisterMapType((map[string]*proto2_proto.SubDefaults)(nil), "proto3_test.Message.Proto2ValueEntry")
proto.RegisterMapType((map[string]string)(nil), "proto3_test.Message.StringMapEntry")
proto.RegisterMapType((map[string]*Nested)(nil), "proto3_test.Message.TerrainEntry")
proto.RegisterType((*Nested)(nil), "proto3_test.Nested")
proto.RegisterType((*MessageWithMap)(nil), "proto3_test.MessageWithMap")
proto.RegisterMapType((map[bool][]byte)(nil), "proto3_test.MessageWithMap.ByteMappingEntry")
proto.RegisterType((*IntMap)(nil), "proto3_test.IntMap")
proto.RegisterMapType((map[int32]int32)(nil), "proto3_test.IntMap.RttEntry")
proto.RegisterType((*IntMaps)(nil), "proto3_test.IntMaps")
proto.RegisterType((*TestUTF8)(nil), "proto3_test.TestUTF8")
proto.RegisterMapType((map[string]int64)(nil), "proto3_test.TestUTF8.MapKeyEntry")
proto.RegisterMapType((map[int64]string)(nil), "proto3_test.TestUTF8.MapValueEntry")
}
func init() { proto.RegisterFile("proto3_proto/proto3.proto", fileDescriptor_1c50d9b824d4ac38) }
func init() { proto.RegisterFile("proto3_proto/test.proto", fileDescriptor_ff83f0b8d2b92afa) }
var fileDescriptor_1c50d9b824d4ac38 = []byte{
// 920 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0xff, 0x6e, 0xe3, 0x44,
0x10, 0x3e, 0xc7, 0xf9, 0xe1, 0x4c, 0x92, 0x5e, 0x58, 0x72, 0xc7, 0x5e, 0x00, 0xc9, 0x04, 0x84,
0x2c, 0x44, 0x1d, 0xc8, 0xa9, 0xa8, 0xdc, 0x9d, 0x40, 0x4d, 0xb9, 0xea, 0xa2, 0x36, 0x21, 0x72,
0x52, 0x2a, 0xf8, 0xc7, 0xda, 0xa4, 0x9b, 0xc4, 0x22, 0x5e, 0x07, 0xef, 0xfa, 0x24, 0xbf, 0x00,
0x0f, 0xc2, 0x2b, 0xf1, 0x42, 0x68, 0x77, 0x9d, 0xd6, 0x39, 0xb9, 0xf4, 0xaf, 0xec, 0x7c, 0xf9,
0x66, 0xbe, 0xd9, 0x99, 0xd9, 0x31, 0xbc, 0xd8, 0xc5, 0x91, 0x88, 0x5e, 0xfa, 0xea, 0xa7, 0xaf,
0x0d, 0x57, 0xfd, 0xa0, 0x66, 0xfe, 0xaf, 0xee, 0x8b, 0x75, 0x14, 0xad, 0xb7, 0x54, 0x53, 0x16,
0xc9, 0xaa, 0x4f, 0x58, 0xaa, 0x89, 0xdd, 0x67, 0x82, 0x72, 0x91, 0x45, 0x90, 0x47, 0x0d, 0xf7,
0xfe, 0xae, 0x43, 0x6d, 0x4c, 0x39, 0x27, 0x6b, 0x8a, 0x10, 0x94, 0x19, 0x09, 0x29, 0x36, 0x6c,
0xc3, 0xa9, 0x7b, 0xea, 0x8c, 0x4e, 0xc1, 0xda, 0x04, 0x5b, 0x12, 0x07, 0x22, 0xc5, 0x25, 0xdb,
0x70, 0x8e, 0x06, 0x9f, 0xb9, 0x79, 0x49, 0x37, 0x73, 0x76, 0xdf, 0x25, 0x61, 0x94, 0xc4, 0xde,
0x1d, 0x1b, 0xd9, 0xd0, 0xdc, 0xd0, 0x60, 0xbd, 0x11, 0x7e, 0xc0, 0xfc, 0x65, 0x88, 0x4d, 0xdb,
0x70, 0x5a, 0x1e, 0x68, 0x6c, 0xc4, 0xce, 0x43, 0xa9, 0x77, 0x4b, 0x04, 0xc1, 0x65, 0xdb, 0x70,
0x9a, 0x9e, 0x3a, 0xa3, 0x2f, 0xa0, 0x19, 0x53, 0x9e, 0x6c, 0x85, 0xbf, 0x8c, 0x12, 0x26, 0x70,
0xcd, 0x36, 0x1c, 0xd3, 0x6b, 0x68, 0xec, 0x5c, 0x42, 0xe8, 0x4b, 0x68, 0x89, 0x38, 0xa1, 0x3e,
0x5f, 0x46, 0x82, 0x87, 0x84, 0x61, 0xcb, 0x36, 0x1c, 0xcb, 0x6b, 0x4a, 0x70, 0x96, 0x61, 0xa8,
0x03, 0x15, 0xbe, 0x8c, 0x62, 0x8a, 0xeb, 0xb6, 0xe1, 0x94, 0x3c, 0x6d, 0xa0, 0x36, 0x98, 0x7f,
0xd2, 0x14, 0x57, 0x6c, 0xd3, 0x29, 0x7b, 0xf2, 0x88, 0x3e, 0x85, 0x3a, 0xdf, 0x44, 0xb1, 0xf0,
0x25, 0xfe, 0xb1, 0x6d, 0x3a, 0x15, 0xcf, 0x52, 0xc0, 0x25, 0x4d, 0xd1, 0xb7, 0x50, 0x65, 0x94,
0x0b, 0x7a, 0x8b, 0xab, 0xb6, 0xe1, 0x34, 0x06, 0x9d, 0xc3, 0xab, 0x4f, 0xd4, 0x7f, 0x5e, 0xc6,
0x41, 0x27, 0x50, 0x8b, 0xfd, 0x55, 0xc2, 0x58, 0x8a, 0xdb, 0xb6, 0xf9, 0x68, 0xa5, 0xaa, 0xf1,
0x85, 0xe4, 0xa2, 0x37, 0x50, 0x13, 0x34, 0x8e, 0x49, 0xc0, 0x30, 0xd8, 0xa6, 0xd3, 0x18, 0xf4,
0x8a, 0xdd, 0xe6, 0x9a, 0xf4, 0x96, 0x89, 0x38, 0xf5, 0xf6, 0x2e, 0xe8, 0x15, 0xe8, 0x09, 0x18,
0xf8, 0xab, 0x80, 0x6e, 0x6f, 0x71, 0x43, 0x25, 0xfa, 0x89, 0x7b, 0xdf, 0x6d, 0x77, 0x96, 0x2c,
0x7e, 0xa1, 0x2b, 0x92, 0x6c, 0x05, 0xf7, 0x1a, 0x9a, 0x7c, 0x21, 0xb9, 0x68, 0x74, 0xe7, 0xfb,
0x9e, 0x6c, 0x13, 0x8a, 0x5b, 0x4a, 0xfe, 0xeb, 0x62, 0xf9, 0xa9, 0x62, 0xfe, 0x26, 0x89, 0x3a,
0x85, 0x2c, 0x94, 0x42, 0xd0, 0x77, 0x60, 0x11, 0x96, 0x8a, 0x4d, 0xc0, 0xd6, 0xf8, 0x28, 0xab,
0x95, 0x9e, 0x45, 0x77, 0x3f, 0x8b, 0xee, 0x19, 0x4b, 0xbd, 0x3b, 0x16, 0x3a, 0x81, 0x46, 0x48,
0x58, 0xea, 0x2b, 0x8b, 0xe3, 0xa7, 0x4a, 0xbb, 0xd8, 0x09, 0x24, 0x71, 0xae, 0x78, 0xe8, 0x04,
0x80, 0x27, 0x8b, 0x50, 0x27, 0x85, 0x3f, 0x52, 0x52, 0xcf, 0x0a, 0x33, 0xf6, 0x72, 0x44, 0xf4,
0x3d, 0x58, 0xcb, 0x4d, 0xb0, 0xbd, 0x8d, 0x29, 0xc3, 0x48, 0x49, 0x3d, 0xe0, 0x74, 0x47, 0x43,
0xe7, 0x00, 0x5c, 0xc4, 0x01, 0x5b, 0xfb, 0x21, 0xd9, 0xe1, 0x8e, 0x72, 0xfa, 0xaa, 0xb8, 0x36,
0x33, 0xc5, 0x1b, 0x93, 0x9d, 0xae, 0x4c, 0x9d, 0xef, 0xed, 0xee, 0x14, 0x9a, 0xf9, 0xbe, 0xed,
0x07, 0x50, 0xbf, 0x30, 0x35, 0x80, 0xdf, 0x40, 0x45, 0x57, 0xbf, 0xf4, 0x3f, 0x23, 0xa6, 0x29,
0xaf, 0x4a, 0xa7, 0x46, 0xf7, 0x06, 0xda, 0x1f, 0xb6, 0xa2, 0x20, 0xea, 0xf1, 0x61, 0xd4, 0x07,
0xe7, 0x21, 0x17, 0xf8, 0x0d, 0x1c, 0x1d, 0xde, 0xa3, 0x20, 0x6c, 0x27, 0x1f, 0xb6, 0x9e, 0xf3,
0xee, 0xfd, 0x0c, 0x55, 0x3d, 0xd7, 0xa8, 0x01, 0xb5, 0xeb, 0xc9, 0xe5, 0xe4, 0xd7, 0x9b, 0x49,
0xfb, 0x09, 0xb2, 0xa0, 0x3c, 0xbd, 0x9e, 0xcc, 0xda, 0x06, 0x6a, 0x41, 0x7d, 0x76, 0x75, 0x36,
0x9d, 0xcd, 0x47, 0xe7, 0x97, 0xed, 0x12, 0x7a, 0x0a, 0x8d, 0xe1, 0xe8, 0xea, 0xca, 0x1f, 0x9e,
0x8d, 0xae, 0xde, 0xfe, 0xde, 0x36, 0x7b, 0x03, 0xa8, 0xea, 0xcb, 0x4a, 0x91, 0x85, 0x7a, 0x45,
0x5a, 0x58, 0x1b, 0x72, 0x59, 0x2c, 0x13, 0xa1, 0x95, 0x2d, 0x4f, 0x9d, 0x7b, 0xff, 0x18, 0x70,
0x94, 0xf5, 0xe0, 0x26, 0x10, 0x9b, 0x31, 0xd9, 0xa1, 0x29, 0x34, 0x17, 0xa9, 0xa0, 0xb2, 0x67,
0x3b, 0x39, 0x8c, 0x86, 0xea, 0xdb, 0x71, 0x61, 0xdf, 0x32, 0x1f, 0x77, 0x98, 0x0a, 0x3a, 0xd6,
0xfc, 0x6c, 0xb4, 0x17, 0xf7, 0x48, 0xf7, 0x27, 0x68, 0x7f, 0x48, 0xc8, 0x57, 0xc6, 0x2a, 0xa8,
0x4c, 0x33, 0x5f, 0x99, 0xbf, 0xa0, 0x3a, 0x62, 0x42, 0xe6, 0xd6, 0x07, 0x33, 0x16, 0x22, 0x4b,
0xe9, 0xf3, 0xc3, 0x94, 0x34, 0xc5, 0xf5, 0x84, 0xd0, 0x29, 0x48, 0x66, 0xf7, 0x07, 0xb0, 0xf6,
0x40, 0x5e, 0xb2, 0x52, 0x20, 0x59, 0xc9, 0x4b, 0xbe, 0x84, 0x9a, 0x8e, 0xc7, 0x91, 0x03, 0xe5,
0x90, 0xec, 0x78, 0x26, 0xda, 0x29, 0x12, 0xf5, 0x14, 0xa3, 0xf7, 0x6f, 0x09, 0xac, 0x39, 0xe5,
0xe2, 0x7a, 0x7e, 0x71, 0x8a, 0x9e, 0x43, 0x95, 0x2f, 0xc9, 0x96, 0xc4, 0x59, 0x13, 0x32, 0x4b,
0xe2, 0xef, 0xe9, 0x52, 0x44, 0x31, 0x2e, 0xd9, 0xa6, 0xc4, 0xb5, 0x85, 0x9e, 0x43, 0x45, 0xef,
0x1f, 0xb9, 0xe5, 0xeb, 0xef, 0x9e, 0x78, 0xda, 0x44, 0xaf, 0xa1, 0x16, 0x92, 0x9d, 0x5a, 0xae,
0xe5, 0xa2, 0xe5, 0xb6, 0x17, 0x74, 0xc7, 0x64, 0x77, 0x49, 0x53, 0x7d, 0xf7, 0x6a, 0xa8, 0x0c,
0x74, 0x06, 0x75, 0xe9, 0xac, 0x2f, 0x59, 0x29, 0x7a, 0x80, 0x79, 0xf7, 0xdc, 0x6a, 0xb2, 0xc2,
0xcc, 0xec, 0xfe, 0x08, 0x8d, 0x5c, 0xe4, 0xc7, 0x26, 0xda, 0xcc, 0xbf, 0x87, 0xd7, 0xd0, 0x3a,
0x88, 0x9a, 0x77, 0x36, 0x1f, 0x79, 0x0e, 0xc3, 0x1a, 0x54, 0x22, 0x46, 0xa3, 0xd5, 0xb0, 0xff,
0xc7, 0xf1, 0x3a, 0x10, 0x9b, 0x64, 0xe1, 0x2e, 0xa3, 0xb0, 0xbf, 0x8e, 0xb6, 0x84, 0xad, 0xef,
0x3f, 0xcf, 0xf9, 0x0f, 0xba, 0xbe, 0xd2, 0xa2, 0xaa, 0xad, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff,
0xae, 0xc1, 0x78, 0xeb, 0xf4, 0x07, 0x00, 0x00,
var fileDescriptor_ff83f0b8d2b92afa = []byte{
// 926 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x6d, 0x6f, 0xdb, 0x36,
0x10, 0xae, 0x2c, 0xbf, 0xc8, 0x67, 0x3b, 0xf5, 0x98, 0xa0, 0xe3, 0xdc, 0x7d, 0x50, 0x5d, 0x0c,
0xd3, 0xb0, 0x41, 0x1e, 0xbc, 0x6e, 0xeb, 0x9a, 0xbd, 0xc5, 0x59, 0x83, 0x18, 0x89, 0x9d, 0x40,
0x76, 0xd6, 0x6d, 0x5f, 0x04, 0xda, 0xa1, 0x6d, 0x61, 0x12, 0x65, 0x88, 0x54, 0x01, 0xfd, 0x9c,
0xfd, 0xa4, 0xfd, 0xa2, 0x0d, 0x24, 0xe5, 0x54, 0x6e, 0x15, 0xe4, 0x93, 0x79, 0x8f, 0x9f, 0xbb,
0xe7, 0x78, 0x77, 0x3c, 0xc1, 0xc7, 0xdb, 0x24, 0x16, 0xf1, 0x37, 0xbe, 0xfa, 0x19, 0x08, 0xca,
0x85, 0xab, 0x8e, 0xa8, 0x95, 0xff, 0x21, 0xa1, 0xde, 0x27, 0xeb, 0x38, 0x5e, 0x87, 0x74, 0xa0,
0xb0, 0x45, 0xba, 0x1a, 0x10, 0x96, 0x69, 0x5e, 0x4f, 0x07, 0x18, 0x7e, 0x10, 0xa0, 0xff, 0x9f,
0x05, 0x8d, 0x09, 0xe5, 0x9c, 0xac, 0x29, 0x42, 0x50, 0x65, 0x24, 0xa2, 0xd8, 0xb0, 0x0d, 0xa7,
0xe9, 0xa9, 0x33, 0xfa, 0x1e, 0xac, 0x4d, 0x10, 0x92, 0x24, 0x10, 0x19, 0xae, 0xd8, 0x86, 0x73,
0x30, 0x7c, 0xea, 0x16, 0x34, 0xdd, 0xdc, 0xd7, 0x3d, 0x4f, 0xa3, 0x38, 0x4d, 0xbc, 0x3b, 0x32,
0xb2, 0xa1, 0xbd, 0xa1, 0xc1, 0x7a, 0x23, 0xfc, 0x80, 0xf9, 0xcb, 0x08, 0x9b, 0xb6, 0xe1, 0x74,
0x3c, 0xd0, 0xd8, 0x98, 0x9d, 0x46, 0x52, 0xee, 0x96, 0x08, 0x82, 0xab, 0xb6, 0xe1, 0xb4, 0x3d,
0x75, 0x46, 0xcf, 0xa0, 0x9d, 0x50, 0x9e, 0x86, 0xc2, 0x5f, 0xc6, 0x29, 0x13, 0xb8, 0x61, 0x1b,
0x8e, 0xe9, 0xb5, 0x34, 0x76, 0x2a, 0x21, 0xf4, 0x1c, 0x3a, 0x22, 0x49, 0xa9, 0xcf, 0x97, 0xb1,
0xe0, 0x11, 0x61, 0xd8, 0xb2, 0x0d, 0xc7, 0xf2, 0xda, 0x12, 0x9c, 0xe5, 0x18, 0x3a, 0x82, 0x1a,
0x5f, 0xc6, 0x09, 0xc5, 0x4d, 0xdb, 0x70, 0x2a, 0x9e, 0x36, 0x50, 0x17, 0xcc, 0xbf, 0x69, 0x86,
0x6b, 0xb6, 0xe9, 0x54, 0x3d, 0x79, 0x44, 0x4f, 0xa1, 0xc9, 0x37, 0x71, 0x22, 0x7c, 0x89, 0x1f,
0xda, 0xa6, 0x53, 0xf3, 0x2c, 0x05, 0x5c, 0xd0, 0x0c, 0x7d, 0x09, 0x75, 0x46, 0xb9, 0xa0, 0xb7,
0xb8, 0x6e, 0x1b, 0x4e, 0x6b, 0x78, 0xb8, 0x77, 0xf3, 0xa9, 0xfa, 0xcb, 0xcb, 0x29, 0xe8, 0x05,
0x34, 0x12, 0x7f, 0x95, 0x32, 0x96, 0xe1, 0xae, 0x6d, 0x3e, 0x54, 0xa7, 0x7a, 0x72, 0x26, 0xa9,
0xe8, 0x18, 0x1a, 0x82, 0x26, 0x09, 0x09, 0x18, 0x06, 0xdb, 0x74, 0x5a, 0xc3, 0x67, 0xa5, 0x5e,
0x73, 0xcd, 0x79, 0xcd, 0x44, 0x92, 0x79, 0x3b, 0x0f, 0x74, 0x0c, 0xed, 0xbc, 0xad, 0xab, 0x80,
0x86, 0xb7, 0xb8, 0xa5, 0xb2, 0xc4, 0x6e, 0x0e, 0xaa, 0x08, 0xb3, 0x74, 0xf1, 0x1b, 0x5d, 0x91,
0x34, 0x14, 0xdc, 0xd3, 0xc3, 0x32, 0x3c, 0x93, 0x64, 0x74, 0x7e, 0xe7, 0xfc, 0x96, 0x84, 0x29,
0xc5, 0x1d, 0x25, 0xff, 0x59, 0xa9, 0xfc, 0xb5, 0x22, 0xfe, 0x2e, 0x79, 0x3a, 0x85, 0x3c, 0x92,
0x42, 0xd0, 0xd7, 0x60, 0x11, 0x96, 0x89, 0x4d, 0xc0, 0xd6, 0xf8, 0x40, 0xa5, 0x70, 0xe4, 0xea,
0x49, 0x74, 0x77, 0x93, 0xe8, 0x9e, 0xb0, 0xcc, 0xbb, 0x63, 0xa1, 0x6f, 0xa1, 0x15, 0x11, 0x96,
0xf9, 0xca, 0xe2, 0xf8, 0xb1, 0x92, 0x2e, 0x77, 0x02, 0x49, 0x9c, 0x2b, 0x1e, 0x7a, 0x01, 0xc0,
0xd3, 0x45, 0xa4, 0x93, 0xc2, 0x1f, 0xe5, 0x52, 0x25, 0x09, 0x7b, 0x05, 0x9e, 0x4c, 0x6f, 0xb9,
0x09, 0xc2, 0xdb, 0x84, 0x32, 0x8c, 0x72, 0xa5, 0x32, 0x9f, 0x3b, 0x16, 0x1a, 0x01, 0x70, 0x91,
0x04, 0x6c, 0xed, 0x47, 0x64, 0x8b, 0x8f, 0x94, 0xcf, 0xf3, 0xd2, 0xc2, 0xcc, 0x14, 0x6d, 0x42,
0xb6, 0xba, 0x2c, 0x4d, 0xbe, 0xb3, 0x7b, 0x57, 0xd0, 0x2e, 0x36, 0x6d, 0x37, 0x7a, 0xfa, 0x69,
0xa9, 0xd1, 0xfb, 0x02, 0x6a, 0xba, 0xf2, 0x95, 0xfb, 0x87, 0x4b, 0x33, 0x5e, 0x55, 0x5e, 0x1a,
0xbd, 0x3f, 0xa0, 0xfb, 0x7e, 0x1b, 0x4a, 0x82, 0xba, 0xfb, 0x41, 0xef, 0x9f, 0x85, 0x42, 0xe4,
0x1f, 0xe1, 0x60, 0xff, 0x1e, 0x25, 0x71, 0x8f, 0x8a, 0x71, 0x9b, 0x05, 0xef, 0xfe, 0x2f, 0x50,
0xd7, 0x33, 0x8d, 0x5a, 0xd0, 0xb8, 0x99, 0x5e, 0x4c, 0xaf, 0xde, 0x4c, 0xbb, 0x8f, 0x90, 0x05,
0xd5, 0xeb, 0x9b, 0xe9, 0xac, 0x6b, 0xa0, 0x0e, 0x34, 0x67, 0x97, 0x27, 0xd7, 0xb3, 0xf9, 0xf8,
0xf4, 0xa2, 0x5b, 0x41, 0x8f, 0xa1, 0x35, 0x1a, 0x5f, 0x5e, 0xfa, 0xa3, 0x93, 0xf1, 0xe5, 0xeb,
0x3f, 0xbb, 0x66, 0x7f, 0x08, 0x75, 0x7d, 0x5b, 0x29, 0xb2, 0x50, 0x0f, 0x48, 0x0b, 0x6b, 0x43,
0xae, 0x89, 0x65, 0x2a, 0xb4, 0xb2, 0xe5, 0xa9, 0x73, 0xff, 0x1f, 0x03, 0x0e, 0xf2, 0x1e, 0xbc,
0x09, 0xc4, 0x66, 0x42, 0xb6, 0xe8, 0x0a, 0xda, 0x8b, 0x4c, 0x50, 0xd9, 0xb2, 0xad, 0x9c, 0x44,
0x43, 0xb5, 0xed, 0xab, 0xb2, 0xb6, 0xe5, 0x2e, 0xee, 0x28, 0x13, 0x74, 0xa2, 0xe9, 0xf9, 0x58,
0x2f, 0xde, 0x21, 0xbd, 0x9f, 0xa1, 0xfb, 0x3e, 0xa1, 0x58, 0x18, 0xab, 0xa4, 0x30, 0xed, 0x62,
0x61, 0xb6, 0x50, 0x1f, 0x33, 0x21, 0x53, 0x73, 0xc1, 0x4c, 0x84, 0xc8, 0x33, 0xfa, 0x74, 0x2f,
0x23, 0xcd, 0x70, 0x3d, 0x21, 0x74, 0x06, 0x92, 0xd8, 0xfb, 0x0e, 0xac, 0x1d, 0x50, 0x54, 0xac,
0x95, 0x28, 0xd6, 0x8a, 0x8a, 0x43, 0x68, 0xe8, 0x78, 0x1c, 0x7d, 0x0e, 0xd5, 0x88, 0x6c, 0x79,
0xae, 0x79, 0x58, 0xa2, 0xe9, 0x29, 0x42, 0xff, 0xdf, 0x0a, 0x58, 0x73, 0xca, 0xc5, 0xcd, 0xfc,
0xec, 0x25, 0x7a, 0x02, 0x75, 0xbe, 0x24, 0x21, 0x49, 0xf2, 0x0e, 0xe4, 0x96, 0xc4, 0xdf, 0xd2,
0xa5, 0x88, 0x13, 0x5c, 0xb1, 0x4d, 0x89, 0x6b, 0x0b, 0x3d, 0x81, 0x9a, 0xde, 0x3c, 0x72, 0xb9,
0x37, 0xcf, 0x1f, 0x79, 0xda, 0x44, 0xaf, 0xa0, 0x11, 0x91, 0xad, 0xda, 0xa9, 0xd5, 0x92, 0xad,
0xb6, 0xd3, 0x73, 0x27, 0x64, 0x7b, 0x41, 0x33, 0x7d, 0xf3, 0x7a, 0xa4, 0x0c, 0xf4, 0x2b, 0x34,
0xa5, 0xaf, 0xbe, 0x62, 0xad, 0xe4, 0xed, 0x15, 0xbd, 0x0b, 0x2b, 0xc9, 0x8a, 0x72, 0xb3, 0xf7,
0x03, 0xb4, 0x0a, 0x81, 0x1f, 0x1a, 0x66, 0xb3, 0xf8, 0x14, 0x8e, 0xa1, 0xb3, 0x17, 0xb5, 0xe8,
0x6c, 0x3e, 0xf0, 0x12, 0x46, 0x0d, 0xa8, 0xc5, 0x8c, 0xc6, 0xab, 0xd1, 0x4f, 0x7f, 0x1d, 0xaf,
0x03, 0xb1, 0x49, 0x17, 0xee, 0x32, 0x8e, 0x06, 0xeb, 0x38, 0x24, 0x6c, 0xfd, 0xee, 0xa3, 0x1c,
0x30, 0x41, 0x13, 0x46, 0x42, 0xf5, 0x15, 0x56, 0x28, 0x1f, 0x14, 0x3f, 0xef, 0x8b, 0xba, 0xb6,
0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x10, 0x03, 0x1b, 0x06, 0xf5, 0x07, 0x00, 0x00,
}

Просмотреть файл

@ -0,0 +1,72 @@
// Copyright 2014 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.
syntax = "proto3";
option go_package = "github.com/golang/protobuf/internal/testprotos/proto3_proto";
import "google/protobuf/any.proto";
import "proto2_proto/test.proto";
package proto3_test;
message Message {
enum Humour {
UNKNOWN = 0;
PUNS = 1;
SLAPSTICK = 2;
BILL_BAILEY = 3;
}
string name = 1;
Humour hilarity = 2;
uint32 height_in_cm = 3;
bytes data = 4;
int64 result_count = 7;
bool true_scotsman = 8;
float score = 9;
repeated uint64 key = 5;
repeated int32 short_key = 19;
Nested nested = 6;
repeated Humour r_funny = 16;
map<string, Nested> terrain = 10;
proto2_test.SubDefaults proto2_field = 11;
map<string, proto2_test.SubDefaults> proto2_value = 13;
google.protobuf.Any anything = 14;
repeated google.protobuf.Any many_things = 15;
Message submessage = 17;
repeated Message children = 18;
map<string, string> string_map = 20;
}
message Nested {
string bunny = 1;
bool cute = 2;
}
message MessageWithMap {
map<bool, bytes> byte_mapping = 1;
}
message IntMap {
map<int32, int32> rtt = 1;
}
message IntMaps {
repeated IntMap maps = 1;
}
message TestUTF8 {
string scalar = 1;
repeated string vector = 2;
oneof oneof { string field = 3; }
map<string, int64> map_key = 4;
map<int64, string> map_value = 5;
}

Просмотреть файл

@ -0,0 +1,17 @@
#!/bin/bash
# Copyright 2020 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.
# NOTE: The integration scripts deliberately do not check to
# make sure that the test protos have been regenerated.
# It is intentional that older versions of the .pb.go files
# are checked in to ensure that they continue to function.
#
# Versions used:
# protoc: v3.9.1
# protoc-gen-go: v1.3.2
for X in $(find . -name "*.proto" | sed "s|^\./||"); do
protoc -I$(pwd) --go_out=paths=source_relative:. $X
done

Просмотреть файл

@ -168,7 +168,6 @@ func SizeTag(num Number) int {
// AppendVarint appends v to b as a varint-encoded uint64.
func AppendVarint(b []byte, v uint64) []byte {
// TODO: Specialize for sizes 1 and 2 with mid-stack inlining.
switch {
case v < 1<<7:
b = append(b, byte(v))
@ -251,7 +250,6 @@ func AppendVarint(b []byte, v uint64) []byte {
// ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeVarint(b []byte) (v uint64, n int) {
// TODO: Specialize for sizes 1 and 2 with mid-stack inlining.
var y uint64
if len(b) <= 0 {
return 0, errCodeTruncated
@ -435,6 +433,18 @@ func SizeBytes(n int) int {
return SizeVarint(uint64(n)) + n
}
// AppendString appends v to b as a length-prefixed bytes value.
func AppendString(b []byte, v string) []byte {
return append(AppendVarint(b, uint64(len(v))), v...)
}
// ConsumeString parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeString(b []byte) (v string, n int) {
bb, n := ConsumeBytes(b)
return string(bb), n
}
// AppendGroup appends v to b as group value, with a trailing end group marker.
// The value v must not contain the end marker.
func AppendGroup(b []byte, num Number, v []byte) []byte {
@ -469,7 +479,7 @@ func SizeGroup(num Number, n int) int {
}
// DecodeTag decodes the field Number and wire Type from its unified form.
// The Number is -1 if the decoded field number overflows.
// The Number is -1 if the decoded field number overflows int32.
// Other than overflow, this does not check for field number validity.
func DecodeTag(x uint64) (Number, Type) {
// NOTE: MessageSet allows for larger field numbers than normal.

512
jsonpb/decode.go Normal file
Просмотреть файл

@ -0,0 +1,512 @@
// Copyright 2015 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.
package jsonpb
import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"reflect"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/encoding/protojson"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
const wrapJSONUnmarshalV2 = false
// UnmarshalNext unmarshals the next object in a JSON object stream into m.
func UnmarshalNext(d *json.Decoder, m proto.Message) error {
return new(Unmarshaler).UnmarshalNext(d, m)
}
// Unmarshal unmarshals a JSON object from r into m.
func Unmarshal(r io.Reader, m proto.Message) error {
return new(Unmarshaler).Unmarshal(r, m)
}
// UnmarshalString unmarshals a JSON object from s into m.
func UnmarshalString(s string, m proto.Message) error {
return new(Unmarshaler).Unmarshal(strings.NewReader(s), m)
}
// Unmarshaler is a configurable object for converting from a JSON
// representation to a protocol buffer object.
type Unmarshaler struct {
// AllowUnknownFields specifies whether to allow messages to contain
// unknown JSON fields, as opposed to failing to unmarshal.
AllowUnknownFields bool
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
// If unset, the global registry is used by default.
AnyResolver AnyResolver
}
// JSONPBUnmarshaler is implemented by protobuf messages that customize the way
// they are unmarshaled from JSON. Messages that implement this should also
// implement JSONPBMarshaler so that the custom format can be produced.
//
// The JSON unmarshaling must follow the JSON to proto specification:
// https://developers.google.com/protocol-buffers/docs/proto3#json
//
// Deprecated: Custom types should implement protobuf reflection instead.
type JSONPBUnmarshaler interface {
UnmarshalJSONPB(*Unmarshaler, []byte) error
}
// Unmarshal unmarshals a JSON object from r into m.
func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error {
return u.UnmarshalNext(json.NewDecoder(r), m)
}
// UnmarshalNext unmarshals the next object in a JSON object stream into m.
func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error {
if m == nil {
return errors.New("invalid nil message")
}
// Parse the next JSON object from the stream.
raw := json.RawMessage{}
if err := d.Decode(&raw); err != nil {
return err
}
// Check for custom unmarshalers first since they may not properly
// implement protobuf reflection that the logic below relies on.
if jsu, ok := m.(JSONPBUnmarshaler); ok {
return jsu.UnmarshalJSONPB(u, raw)
}
mr := protoimpl.X.MessageOf(m)
// NOTE: For historical reasons, a top-level null is treated as a noop.
// This is incorrect, but kept for compatibility.
if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" {
return nil
}
if wrapJSONUnmarshalV2 {
// NOTE: If input message is non-empty, we need to preserve merge semantics
// of the old jsonpb implementation. These semantics are not supported by
// the protobuf JSON specification.
isEmpty := true
mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
isEmpty = false // at least one iteration implies non-empty
return false
})
if !isEmpty {
// Perform unmarshaling into a newly allocated, empty message.
mr = mr.New()
// Use a defer to copy all unmarshaled fields into the original message.
dst := protoimpl.X.MessageOf(m)
defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
dst.Set(fd, v)
return true
})
}
// Unmarshal using the v2 JSON unmarshaler.
opts := protojson.UnmarshalOptions{
DiscardUnknown: u.AllowUnknownFields,
}
if u.AnyResolver != nil {
opts.Resolver = anyResolver{u.AnyResolver}
}
return opts.Unmarshal(raw, mr.Interface())
} else {
if err := u.unmarshalMessage(mr, raw); err != nil {
return err
}
return protoV2.IsInitialized(mr.Interface())
}
}
func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error {
md := m.Descriptor()
fds := md.Fields()
if string(in) == "null" && md.FullName() != "google.protobuf.Value" {
return nil
}
if jsu, ok := protoimpl.X.ProtoMessageV1Of(m.Interface()).(JSONPBUnmarshaler); ok {
return jsu.UnmarshalJSONPB(u, in)
}
switch wellKnownType(md.FullName()) {
case "Any":
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return err
}
rawTypeURL, ok := jsonObject["@type"]
if !ok {
return errors.New("Any JSON doesn't have '@type'")
}
typeURL, err := unquoteString(string(rawTypeURL))
if err != nil {
return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL)
}
m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL))
var m2 protoreflect.Message
if u.AnyResolver != nil {
mi, err := u.AnyResolver.Resolve(typeURL)
if err != nil {
return err
}
m2 = protoimpl.X.MessageOf(mi)
} else {
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
if err != nil {
if err == protoregistry.NotFound {
return fmt.Errorf("could not resolve Any message type: %v", typeURL)
}
return err
}
m2 = mt.New()
}
if wellKnownType(m2.Descriptor().FullName()) != "" {
rawValue, ok := jsonObject["value"]
if !ok {
return errors.New("Any JSON doesn't have 'value'")
}
if err := u.unmarshalMessage(m2, rawValue); err != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
}
} else {
delete(jsonObject, "@type")
rawJSON, err := json.Marshal(jsonObject)
if err != nil {
return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err)
}
if err = u.unmarshalMessage(m2, rawJSON); err != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err)
}
}
rawWire, err := protoV2.Marshal(m2.Interface())
if err != nil {
return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err)
}
m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire))
return nil
case "BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue":
fd := fds.ByNumber(1)
v, err := u.unmarshalValue(m.NewField(fd), in, fd)
if err != nil {
return err
}
m.Set(fd, v)
return nil
case "Duration":
v, err := unquoteString(string(in))
if err != nil {
return err
}
d, err := time.ParseDuration(v)
if err != nil {
return fmt.Errorf("bad Duration: %v", err)
}
sec := d.Nanoseconds() / 1e9
nsec := d.Nanoseconds() % 1e9
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
return nil
case "Timestamp":
v, err := unquoteString(string(in))
if err != nil {
return err
}
t, err := time.Parse(time.RFC3339Nano, v)
if err != nil {
return fmt.Errorf("bad Timestamp: %v", err)
}
sec := t.Unix()
nsec := t.Nanosecond()
m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec)))
m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec)))
return nil
case "Value":
switch {
case string(in) == "null":
m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0))
case string(in) == "true":
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true))
case string(in) == "false":
m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false))
case hasPrefixAndSuffix('"', in, '"'):
s, err := unquoteString(string(in))
if err != nil {
return fmt.Errorf("unrecognized type for Value %q", in)
}
m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s))
case hasPrefixAndSuffix('[', in, ']'):
v := m.Mutable(fds.ByNumber(6))
return u.unmarshalMessage(v.Message(), in)
case hasPrefixAndSuffix('{', in, '}'):
v := m.Mutable(fds.ByNumber(5))
return u.unmarshalMessage(v.Message(), in)
default:
f, err := strconv.ParseFloat(string(in), 0)
if err != nil {
return fmt.Errorf("unrecognized type for Value %q", in)
}
m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f))
}
return nil
case "ListValue":
var jsonArray []json.RawMessage
if err := json.Unmarshal(in, &jsonArray); err != nil {
return fmt.Errorf("bad ListValue: %v", err)
}
lv := m.Mutable(fds.ByNumber(1)).List()
for _, raw := range jsonArray {
ve := lv.NewElement()
if err := u.unmarshalMessage(ve.Message(), raw); err != nil {
return err
}
lv.Append(ve)
}
return nil
case "Struct":
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return fmt.Errorf("bad StructValue: %v", err)
}
mv := m.Mutable(fds.ByNumber(1)).Map()
for key, raw := range jsonObject {
kv := protoreflect.ValueOf(key).MapKey()
vv := mv.NewValue()
if err := u.unmarshalMessage(vv.Message(), raw); err != nil {
return fmt.Errorf("bad value in StructValue for key %q: %v", key, err)
}
mv.Set(kv, vv)
}
return nil
}
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return err
}
// Handle known fields.
for i := 0; i < fds.Len(); i++ {
fd := fds.Get(i)
if fd.IsWeak() && fd.Message().IsPlaceholder() {
continue // weak reference is not linked in
}
// Search for any raw JSON value associated with this field.
var raw json.RawMessage
name := string(fd.Name())
if fd.Kind() == protoreflect.GroupKind {
name = string(fd.Message().Name())
}
if v, ok := jsonObject[name]; ok {
delete(jsonObject, name)
raw = v
}
name = string(fd.JSONName())
if v, ok := jsonObject[name]; ok {
delete(jsonObject, name)
raw = v
}
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) {
continue
}
v, err := u.unmarshalValue(m.NewField(fd), raw, fd)
if err != nil {
return err
}
m.Set(fd, v)
}
// Handle extension fields.
for name, raw := range jsonObject {
if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") {
continue
}
// Resolve the extension field by name.
xname := protoreflect.FullName(name[len("[") : len(name)-len("]")])
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
if xt == nil && isMessageSet(md) {
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
}
if xt == nil {
continue
}
delete(jsonObject, name)
fd := xt.TypeDescriptor()
// Unmarshal the field value.
if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd)) {
continue
}
v, err := u.unmarshalValue(m.NewField(fd), raw, fd)
if err != nil {
return err
}
m.Set(fd, v)
}
if !u.AllowUnknownFields && len(jsonObject) > 0 {
for name := range jsonObject {
return fmt.Errorf("unknown field %q in %v", name, md.FullName())
}
}
return nil
}
func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
if md := fd.Message(); md != nil {
return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated
}
return false
}
func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch {
case fd.IsList():
var jsonArray []json.RawMessage
if err := json.Unmarshal(in, &jsonArray); err != nil {
return v, err
}
lv := v.List()
for _, raw := range jsonArray {
ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd)
if err != nil {
return v, err
}
lv.Append(ve)
}
return v, nil
case fd.IsMap():
var jsonObject map[string]json.RawMessage
if err := json.Unmarshal(in, &jsonObject); err != nil {
return v, err
}
kfd := fd.MapKey()
vfd := fd.MapValue()
mv := v.Map()
for key, raw := range jsonObject {
var kv protoreflect.MapKey
if kfd.Kind() == protoreflect.StringKind {
kv = protoreflect.ValueOf(key).MapKey()
} else {
v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd)
if err != nil {
return v, err
}
kv = v.MapKey()
}
vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd)
if err != nil {
return v, err
}
mv.Set(kv, vv)
}
return v, nil
default:
return u.unmarshalSingularValue(v, in, fd)
}
}
var nonFinite = map[string]float64{
`"NaN"`: math.NaN(),
`"Infinity"`: math.Inf(+1),
`"-Infinity"`: math.Inf(-1),
}
func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch fd.Kind() {
case protoreflect.BoolKind:
return unmarshalValue(in, new(bool))
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
return unmarshalValue(trimQuote(in), new(int32))
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return unmarshalValue(trimQuote(in), new(int64))
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
return unmarshalValue(trimQuote(in), new(uint32))
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return unmarshalValue(trimQuote(in), new(uint64))
case protoreflect.FloatKind:
if f, ok := nonFinite[string(in)]; ok {
return protoreflect.ValueOfFloat32(float32(f)), nil
}
return unmarshalValue(trimQuote(in), new(float32))
case protoreflect.DoubleKind:
if f, ok := nonFinite[string(in)]; ok {
return protoreflect.ValueOfFloat64(float64(f)), nil
}
return unmarshalValue(trimQuote(in), new(float64))
case protoreflect.StringKind:
return unmarshalValue(in, new(string))
case protoreflect.BytesKind:
return unmarshalValue(in, new([]byte))
case protoreflect.EnumKind:
if hasPrefixAndSuffix('"', in, '"') {
vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in)))
if vd == nil {
return v, fmt.Errorf("unknown value %v for enum %s", in, fd.Enum().FullName())
}
return protoreflect.ValueOfEnum(vd.Number()), nil
}
return unmarshalValue(in, new(protoreflect.EnumNumber))
case protoreflect.MessageKind, protoreflect.GroupKind:
err := u.unmarshalMessage(v.Message(), in)
return v, err
default:
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
}
}
func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) {
err := json.Unmarshal(in, v)
return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err
}
func unquoteString(in string) (out string, err error) {
err = json.Unmarshal([]byte(in), &out)
return out, err
}
func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool {
if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix {
return true
}
return false
}
// trimQuote is like unquoteString but simply strips surrounding quotes.
// This is incorrect, but is behavior done by the legacy implementation.
func trimQuote(in []byte) []byte {
if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' {
in = in[1 : len(in)-1]
}
return in
}

555
jsonpb/encode.go Normal file
Просмотреть файл

@ -0,0 +1,555 @@
// Copyright 2015 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.
package jsonpb
import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/encoding/protojson"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
const wrapJSONMarshalV2 = false
// Marshaler is a configurable object for marshaling protocol buffer messages
// to the specified JSON representation.
type Marshaler struct {
// OrigName specifies whether to use the original protobuf name for fields.
OrigName bool
// EnumsAsInts specifies whether to render enum values as integers,
// as opposed to string values.
EnumsAsInts bool
// EmitDefaults specifies Whether to render fields with zero values.
EmitDefaults bool
// Indent controls whether the output is compact or not.
// If empty, the output is compact JSON. If non-empty, every JSON object
// entry and JSON array value will be on its own line.
// Each line will be preceded by repeated copies of Indent, where the
// number of copies is the current indentation depth.
Indent string
// AnyResolver is used to resolve the google.protobuf.Any well-known type.
// If unset, the global registry is used by default.
AnyResolver AnyResolver
}
// JSONPBMarshaler is implemented by protobuf messages that customize the
// way they are marshaled to JSON. Messages that implement this should also
// implement JSONPBUnmarshaler so that the custom format can be parsed.
//
// The JSON marshaling must follow the proto to JSON specification:
// https://developers.google.com/protocol-buffers/docs/proto3#json
//
// Deprecated: Custom types should implement protobuf reflection instead.
type JSONPBMarshaler interface {
MarshalJSONPB(*Marshaler) ([]byte, error)
}
// Marshal marshals a protocol buffer into JSON.
func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
b, err := jm.marshal(m)
if len(b) > 0 {
if _, err := w.Write(b); err != nil {
return err
}
}
return err
}
// MarshalToString converts a protocol buffer object to JSON string.
func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
b, err := jm.marshal(m)
if err != nil {
return "", err
}
return string(b), nil
}
func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
v := reflect.ValueOf(m)
if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
return nil, errors.New("Marshal called with nil")
}
// Check for custom marshalers first since they may not properly
// implement protobuf reflection that the logic below relies on.
if jsm, ok := m.(JSONPBMarshaler); ok {
return jsm.MarshalJSONPB(jm)
}
if wrapJSONMarshalV2 {
opts := protojson.MarshalOptions{
UseProtoNames: jm.OrigName,
UseEnumNumbers: jm.EnumsAsInts,
EmitUnpopulated: jm.EmitDefaults,
Indent: jm.Indent,
}
if jm.AnyResolver != nil {
opts.Resolver = anyResolver{jm.AnyResolver}
}
return opts.Marshal(protoimpl.X.MessageOf(m).Interface())
} else {
// Check for unpopulated required fields first.
m2 := protoimpl.X.MessageOf(m)
if err := protoV2.IsInitialized(m2.Interface()); err != nil {
return nil, err
}
w := jsonWriter{Marshaler: jm}
err := w.marshalMessage(m2, "", "")
return w.buf, err
}
}
type jsonWriter struct {
*Marshaler
buf []byte
}
func (w *jsonWriter) write(s string) {
w.buf = append(w.buf, s...)
}
func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
if jsm, ok := protoimpl.X.ProtoMessageV1Of(m.Interface()).(JSONPBMarshaler); ok {
b, err := jsm.MarshalJSONPB(w.Marshaler)
if err != nil {
return err
}
if typeURL != "" {
// we are marshaling this object to an Any type
var js map[string]*json.RawMessage
if err = json.Unmarshal(b, &js); err != nil {
return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
}
turl, err := json.Marshal(typeURL)
if err != nil {
return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
}
js["@type"] = (*json.RawMessage)(&turl)
if b, err = json.Marshal(js); err != nil {
return err
}
}
w.write(string(b))
return nil
}
md := m.Descriptor()
fds := md.Fields()
// Handle well-known types.
const secondInNanos = int64(time.Second / time.Nanosecond)
switch wellKnownType(md.FullName()) {
case "Any":
return w.marshalAny(m, indent)
case "BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue":
fd := fds.ByNumber(1)
return w.marshalValue(fd, m.Get(fd), indent)
case "Duration":
// "Generated output always contains 0, 3, 6, or 9 fractional digits,
// depending on required precision."
s := m.Get(fds.ByNumber(1)).Int()
ns := m.Get(fds.ByNumber(2)).Int()
if ns <= -secondInNanos || ns >= secondInNanos {
return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
}
if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
return errors.New("signs of seconds and nanos do not match")
}
if s < 0 {
ns = -ns
}
x := fmt.Sprintf("%d.%09d", s, ns)
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
w.write(fmt.Sprintf(`"%vs"`, x))
return nil
case "Timestamp":
// "RFC 3339, where generated output will always be Z-normalized
// and uses 0, 3, 6 or 9 fractional digits."
s := m.Get(fds.ByNumber(1)).Int()
ns := m.Get(fds.ByNumber(2)).Int()
if ns < 0 || ns >= secondInNanos {
return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
}
t := time.Unix(s, ns).UTC()
// time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
x := t.Format("2006-01-02T15:04:05.000000000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, "000")
x = strings.TrimSuffix(x, ".000")
w.write(fmt.Sprintf(`"%vZ"`, x))
return nil
case "Value":
// JSON value; which is a null, number, string, bool, object, or array.
od := md.Oneofs().Get(0)
fd := m.WhichOneof(od)
if fd == nil {
return errors.New("nil Value")
}
return w.marshalValue(fd, m.Get(fd), indent)
case "Struct", "ListValue":
// JSON object or array.
fd := fds.ByNumber(1)
return w.marshalValue(fd, m.Get(fd), indent)
}
w.write("{")
if w.Indent != "" {
w.write("\n")
}
firstField := true
if typeURL != "" {
if err := w.marshalTypeURL(indent, typeURL); err != nil {
return err
}
firstField = false
}
for i := 0; i < fds.Len(); {
fd := fds.Get(i)
if od := fd.ContainingOneof(); od != nil {
fd = m.WhichOneof(od)
i += od.Fields().Len()
if fd == nil {
continue
}
} else {
i++
}
v := m.Get(fd)
if !m.Has(fd) {
if !w.EmitDefaults || fd.ContainingOneof() != nil {
continue
}
if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
}
}
if !firstField {
w.writeComma()
}
if err := w.marshalField(fd, v, indent); err != nil {
return err
}
firstField = false
}
// Handle proto2 extensions.
if md.ExtensionRanges().Len() > 0 {
// Collect a sorted list of all extension descriptor and values.
type ext struct {
desc protoreflect.FieldDescriptor
val protoreflect.Value
}
var exts []ext
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.IsExtension() {
exts = append(exts, ext{fd, v})
}
return true
})
sort.Slice(exts, func(i, j int) bool {
return exts[i].desc.Number() < exts[j].desc.Number()
})
for _, ext := range exts {
if !firstField {
w.writeComma()
}
if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
return err
}
firstField = false
}
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
}
w.write("}")
return nil
}
func (w *jsonWriter) writeComma() {
if w.Indent != "" {
w.write(",\n")
} else {
w.write(",")
}
}
func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
// "If the Any contains a value that has a special JSON mapping,
// it will be converted as follows: {"@type": xxx, "value": yyy}.
// Otherwise, the value will be converted into a JSON object,
// and the "@type" field will be inserted to indicate the actual data type."
md := m.Descriptor()
typeURL := m.Get(md.Fields().ByNumber(1)).String()
rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
var m2 protoreflect.Message
if w.AnyResolver != nil {
mi, err := w.AnyResolver.Resolve(typeURL)
if err != nil {
return err
}
m2 = protoimpl.X.MessageOf(mi)
} else {
mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
if err != nil {
return err
}
m2 = mt.New()
}
if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
return err
}
if wellKnownType(m2.Descriptor().FullName()) == "" {
return w.marshalMessage(m2, indent, typeURL)
}
w.write("{")
if w.Indent != "" {
w.write("\n")
}
if err := w.marshalTypeURL(indent, typeURL); err != nil {
return err
}
w.writeComma()
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
w.write(`"value": `)
} else {
w.write(`"value":`)
}
if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
return err
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
}
w.write("}")
return nil
}
func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
}
w.write(`"@type":`)
if w.Indent != "" {
w.write(" ")
}
b, err := json.Marshal(typeURL)
if err != nil {
return err
}
w.write(string(b))
return nil
}
// marshalField writes field description and value to the Writer.
func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
if w.Indent != "" {
w.write(indent)
w.write(w.Indent)
}
w.write(`"`)
switch {
case fd.IsExtension():
// For message set, use the fname of the message as the extension name.
name := string(fd.FullName())
if isMessageSet(fd.ContainingMessage()) {
name = strings.TrimSuffix(name, ".message_set_extension")
}
w.write("[" + name + "]")
case w.OrigName:
name := string(fd.Name())
if fd.Kind() == protoreflect.GroupKind {
name = string(fd.Message().Name())
}
w.write(name)
default:
w.write(string(fd.JSONName()))
}
w.write(`":`)
if w.Indent != "" {
w.write(" ")
}
return w.marshalValue(fd, v, indent)
}
func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
switch {
case fd.IsList():
w.write("[")
comma := ""
lv := v.List()
for i := 0; i < lv.Len(); i++ {
w.write(comma)
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
w.write(w.Indent)
}
if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil {
return err
}
comma = ","
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
}
w.write("]")
return nil
case fd.IsMap():
kfd := fd.MapKey()
vfd := fd.MapValue()
mv := v.Map()
// Collect a sorted list of all map keys and values.
type entry struct{ key, val protoreflect.Value }
var entries []entry
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
entries = append(entries, entry{k.Value(), v})
return true
})
sort.Slice(entries, func(i, j int) bool {
switch kfd.Kind() {
case protoreflect.BoolKind:
return !entries[i].key.Bool() && entries[j].key.Bool()
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return entries[i].key.Int() < entries[j].key.Int()
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return entries[i].key.Uint() < entries[j].key.Uint()
case protoreflect.StringKind:
return entries[i].key.String() < entries[j].key.String()
default:
panic("invalid kind")
}
})
w.write(`{`)
comma := ""
for _, entry := range entries {
w.write(comma)
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
w.write(w.Indent)
}
s := fmt.Sprint(entry.key.Interface())
b, err := json.Marshal(s)
if err != nil {
return err
}
w.write(string(b))
w.write(`:`)
if w.Indent != "" {
w.write(` `)
}
if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil {
return err
}
comma = ","
}
if w.Indent != "" {
w.write("\n")
w.write(indent)
w.write(w.Indent)
}
w.write(`}`)
return nil
default:
return w.marshalSingularValue(fd, v, indent)
}
}
func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
switch {
case !v.IsValid():
w.write("null")
return nil
case fd.Message() != nil:
return w.marshalMessage(v.Message(), indent+w.Indent, "")
case fd.Enum() != nil:
if fd.Enum().FullName() == "google.protobuf.NullValue" {
w.write("null")
return nil
}
vd := fd.Enum().Values().ByNumber(v.Enum())
if vd == nil || w.EnumsAsInts {
w.write(strconv.Itoa(int(v.Enum())))
} else {
w.write(`"` + string(vd.Name()) + `"`)
}
return nil
default:
switch v.Interface().(type) {
case float32, float64:
switch {
case math.IsInf(v.Float(), +1):
w.write(`"Infinity"`)
return nil
case math.IsInf(v.Float(), -1):
w.write(`"-Infinity"`)
return nil
case math.IsNaN(v.Float()):
w.write(`"NaN"`)
return nil
}
case int64, uint64:
w.write(fmt.Sprintf(`"%d"`, v.Interface()))
return nil
}
b, err := json.Marshal(v.Interface())
if err != nil {
return err
}
w.write(string(b))
return nil
}
}

69
jsonpb/json.go Normal file
Просмотреть файл

@ -0,0 +1,69 @@
// Copyright 2015 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.
// Package jsonpb provides marshaling and unmarshaling between a protocol buffer
// message and JSON. It follows the specification at
// https://developers.google.com/protocol-buffers/docs/proto3#json.
//
// Do not rely on the default behavior of the standard encoding/json package
// when called on generated message types as it does not operate correctly.
//
// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson"
// package instead.
package jsonpb
import (
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
// AnyResolver takes a type URL, present in an Any message, and resolves it into
// an instance of the associated message.
type AnyResolver interface {
Resolve(typeURL string) (proto.Message, error)
}
type anyResolver struct{ AnyResolver }
func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
return r.FindMessageByURL(string(message))
}
func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) {
m, err := r.Resolve(url)
if err != nil {
return nil, err
}
return protoimpl.X.MessageTypeOf(m), nil
}
func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
return protoregistry.GlobalTypes.FindExtensionByName(field)
}
func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
}
func wellKnownType(s protoreflect.FullName) string {
if s.Parent() == "google.protobuf" {
switch s.Name() {
case "Empty", "Any",
"BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue",
"Duration", "Timestamp",
"NullValue", "Struct", "Value", "ListValue":
return string(s.Name())
}
}
return ""
}
func isMessageSet(md protoreflect.MessageDescriptor) bool {
ms, ok := md.(interface{ IsMessageSet() bool })
return ok && ms.IsMessageSet()
}

Просмотреть файл

@ -15,11 +15,11 @@ import (
"testing"
"github.com/golang/protobuf/proto"
pb "github.com/golang/protobuf/jsonpb/jsonpb_test_proto"
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/ptypes"
pb2 "github.com/golang/protobuf/internal/testprotos/jsonpb_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
anypb "github.com/golang/protobuf/ptypes/any"
durpb "github.com/golang/protobuf/ptypes/duration"
stpb "github.com/golang/protobuf/ptypes/struct"
@ -34,7 +34,7 @@ var (
Indent: " ",
}
simpleObject = &pb.Simple{
simpleObject = &pb2.Simple{
OInt32: proto.Int32(-32),
OInt32Str: proto.Int32(-32),
OInt64: proto.Int64(-6400000000),
@ -144,7 +144,7 @@ var (
"oBytes": "YmVlcCBib29w"
}`
repeatsObject = &pb.Repeats{
repeatsObject = &pb2.Repeats{
RBool: []bool{true, false, true},
RInt32: []int32{-3, -4, -5},
RInt64: []int64{-123456789, -987654321},
@ -223,17 +223,17 @@ var (
]
}`
innerSimple = &pb.Simple{OInt32: proto.Int32(-32)}
innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)}
innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}}
innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}}
complexObject = &pb.Widget{
Color: pb.Widget_GREEN.Enum(),
RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE},
innerSimple = &pb2.Simple{OInt32: proto.Int32(-32)}
innerSimple2 = &pb2.Simple{OInt64: proto.Int64(25)}
innerRepeats = &pb2.Repeats{RString: []string{"roses", "red"}}
innerRepeats2 = &pb2.Repeats{RString: []string{"violets", "blue"}}
complexObject = &pb2.Widget{
Color: pb2.Widget_GREEN.Enum(),
RColor: []pb2.Widget_Color{pb2.Widget_RED, pb2.Widget_GREEN, pb2.Widget_BLUE},
Simple: innerSimple,
RSimple: []*pb.Simple{innerSimple, innerSimple2},
RSimple: []*pb2.Simple{innerSimple, innerSimple2},
Repeats: innerRepeats,
RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2},
RRepeats: []*pb2.Repeats{innerRepeats, innerRepeats2},
}
complexObjectJSON = `{"color":"GREEN",` +
@ -309,33 +309,33 @@ var (
}
}
}`
realNumber = &pb.Real{Value: proto.Float64(3.14159265359)}
realNumber = &pb2.Real{Value: proto.Float64(3.14159265359)}
realNumberName = "Pi"
complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)}
complexNumber = &pb2.Complex{Imaginary: proto.Float64(0.5772156649)}
realNumberJSON = `{` +
`"value":3.14159265359,` +
`"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` +
`"[jsonpb.name]":"Pi"` +
`"[jsonpb_test.Complex.real_extension]":{"imaginary":0.5772156649},` +
`"[jsonpb_test.name]":"Pi"` +
`}`
anySimple = &pb.KnownTypes{
anySimple = &pb2.KnownTypes{
An: &anypb.Any{
TypeUrl: "something.example.com/jsonpb.Simple",
TypeUrl: "something.example.com/jsonpb_test.Simple",
Value: []byte{
// &pb.Simple{OBool:true}
// &pb2.Simple{OBool:true}
1 << 3, 1,
},
},
}
anySimpleJSON = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}`
anySimpleJSON = `{"an":{"@type":"something.example.com/jsonpb_test.Simple","oBool":true}}`
anySimplePrettyJSON = `{
"an": {
"@type": "something.example.com/jsonpb.Simple",
"@type": "something.example.com/jsonpb_test.Simple",
"oBool": true
}
}`
anyWellKnown = &pb.KnownTypes{
anyWellKnown = &pb2.KnownTypes{
An: &anypb.Any{
TypeUrl: "type.googleapis.com/google.protobuf.Duration",
Value: []byte{
@ -353,7 +353,7 @@ var (
}
}`
nonFinites = &pb.NonFinites{
nonFinites = &pb2.NonFinites{
FNan: proto.Float32(float32(math.NaN())),
FPinf: proto.Float32(float32(math.Inf(1))),
FNinf: proto.Float32(float32(math.Inf(-1))),
@ -372,10 +372,10 @@ var (
)
func init() {
if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil {
if err := proto.SetExtension(realNumber, pb2.E_Name, &realNumberName); err != nil {
panic(err)
}
if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil {
if err := proto.SetExtension(realNumber, pb2.E_Complex_RealExtension, complexNumber); err != nil {
panic(err)
}
}
@ -394,83 +394,83 @@ var marshalingTests = []struct {
{"nested message/enum flat object", marshaler, complexObject, complexObjectJSON},
{"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON},
{"enum-string flat object", Marshaler{},
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
&pb2.Widget{Color: pb2.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
{"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "},
&pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON},
&pb2.Widget{Color: pb2.Widget_BLUE.Enum()}, colorPrettyJSON},
{"unknown enum value object", marshalerAllOptions,
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON},
&pb2.Widget{Color: pb2.Widget_Color(1000).Enum(), RColor: []pb2.Widget_Color{pb2.Widget_RED}}, colorListPrettyJSON},
{"repeated proto3 enum", Marshaler{},
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
&pb3.Message{RFunny: []pb3.Message_Humour{
pb3.Message_PUNS,
pb3.Message_SLAPSTICK,
}},
`{"rFunny":["PUNS","SLAPSTICK"]}`},
{"repeated proto3 enum as int", Marshaler{EnumsAsInts: true},
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
&pb3.Message{RFunny: []pb3.Message_Humour{
pb3.Message_PUNS,
pb3.Message_SLAPSTICK,
}},
`{"rFunny":[1,2]}`},
{"empty value", marshaler, &pb.Simple3{}, `{}`},
{"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`},
{"empty repeated emitted", Marshaler{EmitDefaults: true}, &pb.SimpleSlice3{}, `{"slices":[]}`},
{"empty map emitted", Marshaler{EmitDefaults: true}, &pb.SimpleMap3{}, `{"stringy":{}}`},
{"nested struct null", Marshaler{EmitDefaults: true}, &pb.SimpleNull3{}, `{"simple":null}`},
{"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
{"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
{"empty value", marshaler, &pb2.Simple3{}, `{}`},
{"empty value emitted", Marshaler{EmitDefaults: true}, &pb2.Simple3{}, `{"dub":0}`},
{"empty repeated emitted", Marshaler{EmitDefaults: true}, &pb2.SimpleSlice3{}, `{"slices":[]}`},
{"empty map emitted", Marshaler{EmitDefaults: true}, &pb2.SimpleMap3{}, `{"stringy":{}}`},
{"nested struct null", Marshaler{EmitDefaults: true}, &pb2.SimpleNull3{}, `{"simple":null}`},
{"map<int64, int32>", marshaler, &pb2.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
{"map<int64, int32>", marshalerAllOptions, &pb2.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
{"map<string, string>", marshaler,
&pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
&pb2.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
`{"strry":{"\"one\"":"two","three":"four"}}`},
{"map<int32, Object>", marshaler,
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
&pb2.Mappy{Objjy: map[int32]*pb2.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
{"map<int32, Object>", marshalerAllOptions,
&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, objjyPrettyJSON},
{"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}},
&pb2.Mappy{Objjy: map[int32]*pb2.Simple3{1: {Dub: 1}}}, objjyPrettyJSON},
{"map<int64, string>", marshaler, &pb2.Mappy{Buggy: map[int64]string{1234: "yup"}},
`{"buggy":{"1234":"yup"}}`},
{"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}}`},
{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
{"map<int32, bool>", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<int64, bool>", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint32, bool>", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint64, bool>", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}},
{"map<bool, bool>", marshaler, &pb2.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
{"map<string, enum>", marshaler, &pb2.Mappy{Enumy: map[string]pb2.Numeral{"XIV": pb2.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}}`},
{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb2.Mappy{Enumy: map[string]pb2.Numeral{"XIV": pb2.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
{"map<int32, bool>", marshaler, &pb2.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<int64, bool>", marshaler, &pb2.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint32, bool>", marshaler, &pb2.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"map<uint64, bool>", marshaler, &pb2.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
{"proto2 map<int64, string>", marshaler, &pb2.Maps{MInt64Str: map[int64]string{213: "cat"}},
`{"mInt64Str":{"213":"cat"}}`},
{"proto2 map<bool, Object>", marshaler,
&pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: {OInt32: proto.Int32(1)}}},
&pb2.Maps{MBoolSimple: map[bool]*pb2.Simple{true: {OInt32: proto.Int32(1)}}},
`{"mBoolSimple":{"true":{"oInt32":1}}}`},
{"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`},
{"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`},
{"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)},
{"oneof, not set", marshaler, &pb2.MsgWithOneof{}, `{}`},
{"oneof, set", marshaler, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`},
{"force orig_name", Marshaler{OrigName: true}, &pb2.Simple{OInt32: proto.Int32(4)},
`{"o_int32":4}`},
{"proto2 extension", marshaler, realNumber, realNumberJSON},
{"Any with message", marshaler, anySimple, anySimpleJSON},
{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3s"}`},
{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`},
{"Duration beyond float64 precision", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"negative Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`},
{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
{"Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3s"}`},
{"Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`},
{"Duration beyond float64 precision", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
{"negative Duration", marshaler, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`},
{"Struct", marshaler, &pb2.KnownTypes{St: &stpb.Struct{
Fields: map[string]*stpb.Value{
"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},
"two": {Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}},
},
}}, `{"st":{"one":"loneliest number","two":null}}`},
{"empty ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{}}, `{"lv":[]}`},
{"basic ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
{"empty ListValue", marshaler, &pb2.KnownTypes{Lv: &stpb.ListValue{}}, `{"lv":[]}`},
{"basic ListValue", marshaler, &pb2.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
{Kind: &stpb.Value_StringValue{"x"}},
{Kind: &stpb.Value_NullValue{}},
{Kind: &stpb.Value_NumberValue{3}},
{Kind: &stpb.Value_BoolValue{true}},
}}}, `{"lv":["x",null,3,true]}`},
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
{"number Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}, `{"val":1}`},
{"null Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}, `{"val":null}`},
{"string number value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
{"list of lists Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{
{"Timestamp", marshaler, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
{"Timestamp", marshaler, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
{"number Value", marshaler, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}, `{"val":1}`},
{"null Value", marshaler, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}, `{"val":null}`},
{"string number value", marshaler, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
{"list of lists Value", marshaler, &pb2.KnownTypes{Val: &stpb.Value{
Kind: &stpb.Value_ListValue{&stpb.ListValue{
Values: []*stpb.Value{
{Kind: &stpb.Value_StringValue{"x"}},
@ -486,18 +486,18 @@ var marshalingTests = []struct {
}},
}}, `{"val":["x",[["y"],"z"]]}`},
{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
{"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
{"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`},
{"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`},
{"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`},
{"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`},
{"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`},
{"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`},
{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
{"DoubleValue", marshaler, &pb2.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
{"FloatValue", marshaler, &pb2.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
{"Int64Value", marshaler, &pb2.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`},
{"UInt64Value", marshaler, &pb2.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`},
{"Int32Value", marshaler, &pb2.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`},
{"UInt32Value", marshaler, &pb2.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`},
{"BoolValue", marshaler, &pb2.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`},
{"StringValue", marshaler, &pb2.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`},
{"BytesValue", marshaler, &pb2.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
{"required", marshaler, &pb.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
{"required bytes", marshaler, &pb.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
{"required", marshaler, &pb2.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
{"required bytes", marshaler, &pb2.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
}
func TestMarshaling(t *testing.T) {
@ -512,7 +512,7 @@ func TestMarshaling(t *testing.T) {
}
func TestMarshalingNil(t *testing.T) {
var msg *pb.Simple
var msg *pb2.Simple
m := &Marshaler{}
if _, err := m.MarshalToString(msg); err == nil {
t.Errorf("mashaling nil returned no error")
@ -524,15 +524,15 @@ func TestMarshalIllegalTime(t *testing.T) {
pb proto.Message
fail bool
}{
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 0}}, false},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 1}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 1000000000}}, true},
{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: -1000000000}}, true},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1}}, false},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: -1}}, true},
{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1000000000}}, true},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 0}}, false},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 0}}, false},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: -1}}, true},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 1}}, true},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 1000000000}}, true},
{&pb2.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: -1000000000}}, true},
{&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1}}, false},
{&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: -1}}, true},
{&pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1000000000}}, true},
}
for _, tt := range tests {
_, err := marshaler.MarshalToString(tt.pb)
@ -590,8 +590,8 @@ func TestMarshalWithCustomValidation(t *testing.T) {
// Test marshaling message containing unset required fields should produce error.
func TestMarshalUnsetRequiredFields(t *testing.T) {
msgExt := &pb.Real{}
proto.SetExtension(msgExt, pb.E_Extm, &pb.MsgWithRequired{})
msgExt := &pb2.Real{}
proto.SetExtension(msgExt, pb2.E_Extm, &pb2.MsgWithRequired{})
tests := []struct {
desc string
@ -601,43 +601,43 @@ func TestMarshalUnsetRequiredFields(t *testing.T) {
{
desc: "direct required field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequired{},
pb: &pb2.MsgWithRequired{},
},
{
desc: "direct required field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithRequired{},
pb: &pb2.MsgWithRequired{},
},
{
desc: "indirect required field",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
pb: &pb2.MsgWithIndirectRequired{Subm: &pb2.MsgWithRequired{}},
},
{
desc: "indirect required field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
pb: &pb2.MsgWithIndirectRequired{Subm: &pb2.MsgWithRequired{}},
},
{
desc: "direct required wkt field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequiredWKT{},
pb: &pb2.MsgWithRequiredWKT{},
},
{
desc: "direct required wkt field + emit defaults",
marshaler: &Marshaler{EmitDefaults: true},
pb: &pb.MsgWithRequiredWKT{},
pb: &pb2.MsgWithRequiredWKT{},
},
{
desc: "direct required bytes field",
marshaler: &Marshaler{},
pb: &pb.MsgWithRequiredBytes{},
pb: &pb2.MsgWithRequiredBytes{},
},
{
desc: "required in map value",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{
MapField: map[string]*pb.MsgWithRequired{
pb: &pb2.MsgWithIndirectRequired{
MapField: map[string]*pb2.MsgWithRequired{
"key": {},
},
},
@ -645,8 +645,8 @@ func TestMarshalUnsetRequiredFields(t *testing.T) {
{
desc: "required in repeated item",
marshaler: &Marshaler{},
pb: &pb.MsgWithIndirectRequired{
SliceField: []*pb.MsgWithRequired{
pb: &pb2.MsgWithIndirectRequired{
SliceField: []*pb2.MsgWithRequired{
{Str: proto.String("hello")},
{},
},
@ -655,8 +655,8 @@ func TestMarshalUnsetRequiredFields(t *testing.T) {
{
desc: "required inside oneof",
marshaler: &Marshaler{},
pb: &pb.MsgWithOneof{
Union: &pb.MsgWithOneof_MsgWithRequired{&pb.MsgWithRequired{}},
pb: &pb2.MsgWithOneof{
Union: &pb2.MsgWithOneof_MsgWithRequired{&pb2.MsgWithRequired{}},
},
},
{
@ -685,72 +685,72 @@ var unmarshalingTests = []struct {
{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb2.Widget{Color: pb2.Widget_BLUE.Enum()}},
{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb2.Widget{Color: pb2.Widget_BLUE.Enum()}},
{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb2.Simple)},
{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &pb3.Message{Hilarity: pb3.Message_PUNS}},
{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &pb3.Message{Hilarity: pb3.Message_PUNS}},
{"unknown enum value object",
Unmarshaler{},
"{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}",
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
&pb2.Widget{Color: pb2.Widget_Color(1000).Enum(), RColor: []pb2.Widget_Color{pb2.Widget_RED}}},
{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
&pb3.Message{RFunny: []pb3.Message_Humour{
pb3.Message_PUNS,
pb3.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
&pb3.Message{RFunny: []pb3.Message_Humour{
pb3.Message_PUNS,
pb3.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
&pb3.Message{RFunny: []pb3.Message_Humour{
pb3.Message_PUNS,
pb3.Message_SLAPSTICK,
}}},
{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
{"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb.Simple{ODouble: proto.Float64(math.NaN())}},
{"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}},
{"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb.Simple{ODouble: proto.Float64(math.Inf(-1))}},
{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}},
{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb2.Simple{OInt64: proto.Int64(-314)}},
{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb2.Simple{OUint64: proto.Uint64(123)}},
{"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb2.Simple{ODouble: proto.Float64(math.NaN())}},
{"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb2.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}},
{"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb2.Simple{ODouble: proto.Float64(math.Inf(-1))}},
{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb2.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb2.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb2.Mappy{Objjy: map[int32]*pb2.Simple3{1: {Dub: 1}}}},
{"proto2 extension", Unmarshaler{}, realNumberJSON, realNumber},
{"Any with message", Unmarshaler{}, anySimpleJSON, anySimple},
{"Any with message and indent", Unmarshaler{}, anySimplePrettyJSON, anySimple},
{"Any with WKT", Unmarshaler{}, anyWellKnownJSON, anyWellKnown},
{"Any with WKT and indent", Unmarshaler{}, anyWellKnownPrettyJSON, anyWellKnown},
{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}}`, &pb2.Mappy{Enumy: map[string]pb2.Numeral{"XIV": pb2.Numeral_ROMAN}}},
{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb2.Mappy{Enumy: map[string]pb2.Numeral{"XIV": pb2.Numeral_ROMAN}}},
{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_Salary{31000}}},
{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_Country{"Australia"}}},
{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_Country{"Australia"}}},
{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_HomeAddress{"Australia"}}},
{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb2.MsgWithOneof{Union: &pb2.MsgWithOneof_HomeAddress{"Australia"}}},
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb2.Simple{OBool: proto.Bool(true)}},
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb2.Simple{OBool: proto.Bool(true)}},
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 4}}},
{"Duration with unicode", Unmarshaler{}, `{"dur": "3\u0073"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
{"Timestamp with unicode", Unmarshaler{}, `{"ts": "2014-05-13T16:53:20\u005a"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}},
{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}},
{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}},
{"null Struct", Unmarshaler{}, `{"st": null}`, &pb.KnownTypes{St: nil}},
{"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb.KnownTypes{St: &stpb.Struct{}}},
{"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 4}}},
{"Duration with unicode", Unmarshaler{}, `{"dur": "3\u0073"}`, &pb2.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb2.KnownTypes{Dur: nil}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
{"Timestamp with unicode", Unmarshaler{}, `{"ts": "2014-05-13T16:53:20\u005a"}`, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}},
{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb2.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}},
{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb2.KnownTypes{Ts: nil}},
{"null Struct", Unmarshaler{}, `{"st": null}`, &pb2.KnownTypes{St: nil}},
{"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb2.KnownTypes{St: &stpb.Struct{}}},
{"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb2.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
"a": {Kind: &stpb.Value_StringValue{"x"}},
"b": {Kind: &stpb.Value_NullValue{}},
"c": {Kind: &stpb.Value_NumberValue{3}},
"d": {Kind: &stpb.Value_BoolValue{true}},
}}}},
{"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
{"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb2.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
"a": {Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{
"b": {Kind: &stpb.Value_NumberValue{1}},
"c": {Kind: &stpb.Value_ListValue{&stpb.ListValue{Values: []*stpb.Value{
@ -759,20 +759,20 @@ var unmarshalingTests = []struct {
}}}},
}}}},
}}}},
{"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb.KnownTypes{Lv: nil}},
{"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb.KnownTypes{Lv: &stpb.ListValue{}}},
{"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
{"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb2.KnownTypes{Lv: nil}},
{"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb2.KnownTypes{Lv: &stpb.ListValue{}}},
{"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb2.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
{Kind: &stpb.Value_StringValue{"x"}},
{Kind: &stpb.Value_NullValue{}},
{Kind: &stpb.Value_NumberValue{3}},
{Kind: &stpb.Value_BoolValue{true}},
}}}},
{"number Value", Unmarshaler{}, `{"val":1}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}},
{"null Value", Unmarshaler{}, `{"val":null}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}},
{"bool Value", Unmarshaler{}, `{"val":true}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_BoolValue{true}}}},
{"string Value", Unmarshaler{}, `{"val":"x"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"x"}}}},
{"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}},
{"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb.KnownTypes{Val: &stpb.Value{
{"number Value", Unmarshaler{}, `{"val":1}`, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}},
{"null Value", Unmarshaler{}, `{"val":null}`, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}},
{"bool Value", Unmarshaler{}, `{"val":true}`, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_BoolValue{true}}}},
{"string Value", Unmarshaler{}, `{"val":"x"}`, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"x"}}}},
{"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb2.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}},
{"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb2.KnownTypes{Val: &stpb.Value{
Kind: &stpb.Value_ListValue{&stpb.ListValue{
Values: []*stpb.Value{
{Kind: &stpb.Value_StringValue{"x"}},
@ -787,15 +787,15 @@ var unmarshalingTests = []struct {
},
}}}}},
{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
{"StringValue containing escaped character", Unmarshaler{}, `{"str":"a\/b"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "a/b"}}},
{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb2.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb2.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb2.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb2.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb2.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb2.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb2.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb2.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
{"StringValue containing escaped character", Unmarshaler{}, `{"str":"a\/b"}`, &pb2.KnownTypes{Str: &wpb.StringValue{Value: "a/b"}}},
{"StructValue containing StringValue's", Unmarshaler{}, `{"escaped": "a\/b", "unicode": "\u00004E16\u0000754C"}`,
&stpb.Struct{
Fields: map[string]*stpb.Value{
@ -803,21 +803,21 @@ var unmarshalingTests = []struct {
"unicode": {Kind: &stpb.Value_StringValue{"\u00004E16\u0000754C"}},
},
}},
{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb2.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
// Ensure that `null` as a value ends up with a nil pointer instead of a [type]Value struct.
{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: nil}},
{"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb.KnownTypes{Flt: nil}},
{"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb.KnownTypes{I64: nil}},
{"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb.KnownTypes{U64: nil}},
{"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb.KnownTypes{I32: nil}},
{"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb.KnownTypes{U32: nil}},
{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}},
{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}},
{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}},
{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb2.KnownTypes{Dbl: nil}},
{"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb2.KnownTypes{Flt: nil}},
{"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb2.KnownTypes{I64: nil}},
{"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb2.KnownTypes{U64: nil}},
{"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb2.KnownTypes{I32: nil}},
{"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb2.KnownTypes{U32: nil}},
{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb2.KnownTypes{Bool: nil}},
{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb2.KnownTypes{Str: nil}},
{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb2.KnownTypes{Bytes: nil}},
{"required", Unmarshaler{}, `{"str":"hello"}`, &pb.MsgWithRequired{Str: proto.String("hello")}},
{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb.MsgWithRequiredBytes{Byts: []byte{}}},
{"required", Unmarshaler{}, `{"str":"hello"}`, &pb2.MsgWithRequired{Str: proto.String("hello")}},
{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb2.MsgWithRequiredBytes{Byts: []byte{}}},
}
func TestUnmarshaling(t *testing.T) {
@ -841,21 +841,21 @@ func TestUnmarshaling(t *testing.T) {
}
func TestUnmarshalNullArray(t *testing.T) {
var repeats pb.Repeats
var repeats pb2.Repeats
if err := UnmarshalString(`{"rBool":null}`, &repeats); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(repeats, pb.Repeats{}) {
if !proto.Equal(&repeats, &pb2.Repeats{}) {
t.Errorf("got non-nil fields in [%#v]", repeats)
}
}
func TestUnmarshalNullObject(t *testing.T) {
var maps pb.Maps
var maps pb2.Maps
if err := UnmarshalString(`{"mInt64Str":null}`, &maps); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(maps, pb.Maps{}) {
if !proto.Equal(&maps, &pb2.Maps{}) {
t.Errorf("got non-nil fields in [%#v]", maps)
}
}
@ -889,7 +889,7 @@ func TestUnmarshalNext(t *testing.T) {
}
}
p := &pb.Simple{}
p := &pb2.Simple{}
err := new(Unmarshaler).UnmarshalNext(dec, p)
if err != io.EOF {
t.Errorf("eof: got %v, expected io.EOF", err)
@ -901,15 +901,15 @@ var unmarshalingShouldError = []struct {
in string
pb proto.Message
}{
{"a value", "666", new(pb.Simple)},
{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
{"Duration containing invalid character", `{"dur": "3\U0073"}`, &pb.KnownTypes{}},
{"Timestamp containing invalid character", `{"ts": "2014-05-13T16:53:20\U005a"}`, &pb.KnownTypes{}},
{"StringValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &pb.KnownTypes{}},
{"a value", "666", new(pb2.Simple)},
{"gibberish", "{adskja123;l23=-=", new(pb2.Simple)},
{"unknown field", `{"unknown": "foo"}`, new(pb2.Simple)},
{"unknown enum name", `{"hilarity":"DAVE"}`, new(pb3.Message)},
{"Duration containing invalid character", `{"dur": "3\U0073"}`, &pb2.KnownTypes{}},
{"Timestamp containing invalid character", `{"ts": "2014-05-13T16:53:20\U005a"}`, &pb2.KnownTypes{}},
{"StringValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &pb2.KnownTypes{}},
{"StructValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &stpb.Struct{}},
{"repeated proto3 enum with non array input", `{"rFunny":"PUNS"}`, &proto3pb.Message{RFunny: []proto3pb.Message_Humour{}}},
{"repeated proto3 enum with non array input", `{"rFunny":"PUNS"}`, &pb3.Message{RFunny: []pb3.Message_Humour{}}},
}
func TestUnmarshalingBadInput(t *testing.T) {
@ -931,9 +931,9 @@ func TestAnyWithCustomResolver(t *testing.T) {
var resolvedTypeUrls []string
resolver := funcResolver(func(turl string) (proto.Message, error) {
resolvedTypeUrls = append(resolvedTypeUrls, turl)
return new(pb.Simple), nil
return new(pb2.Simple), nil
})
msg := &pb.Simple{
msg := &pb2.Simple{
OBytes: []byte{1, 2, 3, 4},
OBool: proto.Bool(true),
OString: proto.String("foobar"),
@ -998,7 +998,7 @@ func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
t.Errorf("unmarshal error: %v", err)
}
want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
want := ptrFieldMessage{}
if !proto.Equal(&ptrFieldMsg, &want) {
t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
}
@ -1021,7 +1021,7 @@ func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
}
if !proto.Equal(&got, &want) {
t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", got, want)
t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", &got, &want)
}
}
@ -1112,7 +1112,7 @@ func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
}
var testMessageFD = func() []byte {
fd := new(descriptorpb.FileDescriptorProto)
fd := new(descpb.FileDescriptorProto)
proto.UnmarshalText(`
name: "jsonpb.proto"
package: "github_com.golang.protobuf.jsonpb"
@ -1153,92 +1153,92 @@ func TestUnmarshalUnsetRequiredFields(t *testing.T) {
}{
{
desc: "direct required field missing",
pb: &pb.MsgWithRequired{},
pb: &pb2.MsgWithRequired{},
json: `{}`,
},
{
desc: "direct required field set to null",
pb: &pb.MsgWithRequired{},
pb: &pb2.MsgWithRequired{},
json: `{"str": null}`,
},
{
desc: "indirect required field missing",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"subm": {}}`,
},
{
desc: "indirect required field set to null",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"subm": {"str": null}}`,
},
{
desc: "direct required bytes field missing",
pb: &pb.MsgWithRequiredBytes{},
pb: &pb2.MsgWithRequiredBytes{},
json: `{}`,
},
{
desc: "direct required bytes field set to null",
pb: &pb.MsgWithRequiredBytes{},
pb: &pb2.MsgWithRequiredBytes{},
json: `{"byts": null}`,
},
{
desc: "direct required wkt field missing",
pb: &pb.MsgWithRequiredWKT{},
pb: &pb2.MsgWithRequiredWKT{},
json: `{}`,
},
{
desc: "direct required wkt field set to null",
pb: &pb.MsgWithRequiredWKT{},
pb: &pb2.MsgWithRequiredWKT{},
json: `{"str": null}`,
},
{
desc: "any containing message with required field set to null",
pb: &pb.KnownTypes{},
pb: &pb2.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
},
{
desc: "any containing message with missing required field",
pb: &pb.KnownTypes{},
pb: &pb2.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
},
{
desc: "missing required in map value",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
},
{
desc: "required in map value set to null",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
},
{
desc: "missing required in slice item",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"slice_field": [{}, {"str": "hi"}]}`,
},
{
desc: "required in slice item set to null",
pb: &pb.MsgWithIndirectRequired{},
pb: &pb2.MsgWithIndirectRequired{},
json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
},
{
desc: "required inside oneof missing",
pb: &pb.MsgWithOneof{},
pb: &pb2.MsgWithOneof{},
json: `{"msgWithRequired": {}}`,
},
{
desc: "required inside oneof set to null",
pb: &pb.MsgWithOneof{},
pb: &pb2.MsgWithOneof{},
json: `{"msgWithRequired": {"str": null}}`,
},
{
desc: "required field in extension missing",
pb: &pb.Real{},
pb: &pb2.Real{},
json: `{"[jsonpb.extm]":{}}`,
},
{
desc: "required field in extension set to null",
pb: &pb.Real{},
pb: &pb2.Real{},
json: `{"[jsonpb.extm]":{"str": null}}`,
},
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,71 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option go_package = "github.com/golang/protobuf/jsonpb/jsonpb_test_proto;jsonpb";
package jsonpb;
message Simple3 {
double dub = 1;
}
message SimpleSlice3 {
repeated string slices = 1;
}
message SimpleMap3 {
map<string,string> stringy = 1;
}
message SimpleNull3 {
Simple3 simple = 1;
}
enum Numeral {
UNKNOWN = 0;
ARABIC = 1;
ROMAN = 2;
}
message Mappy {
map<int64, int32> nummy = 1;
map<string, string> strry = 2;
map<int32, Simple3> objjy = 3;
map<int64, string> buggy = 4;
map<bool, bool> booly = 5;
map<string, Numeral> enumy = 6;
map<int32, bool> s32booly = 7;
map<int64, bool> s64booly = 8;
map<uint32, bool> u32booly = 9;
map<uint64, bool> u64booly = 10;
}

324
proto/buffer.go Normal file
Просмотреть файл

@ -0,0 +1,324 @@
// 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.
package proto
import (
"errors"
"fmt"
"github.com/golang/protobuf/internal/wire"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/runtime/protoimpl"
)
const (
WireVarint = 0
WireFixed32 = 5
WireFixed64 = 1
WireBytes = 2
WireStartGroup = 3
WireEndGroup = 4
)
// EncodeVarint returns the varint encoded bytes of v.
func EncodeVarint(v uint64) []byte {
return wire.AppendVarint(nil, v)
}
// SizeVarint returns the length of the varint encoded bytes of v.
// This is equal to len(EncodeVarint(v)).
func SizeVarint(v uint64) int {
return wire.SizeVarint(v)
}
// DecodeVarint parses a varint encoded integer from b, returning the
// integer value and the length of the varint.
// It returns (0, 0) if there is a parse error.
func DecodeVarint(b []byte) (uint64, int) {
v, n := wire.ConsumeVarint(b)
if n < 0 {
return 0, 0
}
return v, n
}
// Buffer is a buffer for encoding and decoding the protobuf wire format.
// It may be reused between invocations to reduce memory usage.
type Buffer struct {
buf []byte
idx int
deterministic bool
}
// NewBuffer allocates a new Buffer initialized with buf,
// where the contents of buf are considered the unread portion of the buffer.
func NewBuffer(buf []byte) *Buffer {
return &Buffer{buf: buf}
}
// SetDeterministic specifies whether to use deterministic serialization.
//
// Deterministic serialization guarantees that for a given binary, equal
// messages will always be serialized to the same bytes. This implies:
//
// - Repeated serialization of a message will return the same bytes.
// - Different processes of the same binary (which may be executing on
// different machines) will serialize equal messages to the same bytes.
//
// Note that the deterministic serialization is NOT canonical across
// languages. It is not guaranteed to remain stable over time. It is unstable
// across different builds with schema changes due to unknown fields.
// Users who need canonical serialization (e.g., persistent storage in a
// canonical form, fingerprinting, etc.) should define their own
// canonicalization specification and implement their own serializer rather
// than relying on this API.
//
// If deterministic serialization is requested, map entries will be sorted
// by keys in lexographical order. This is an implementation detail and
// subject to change.
func (b *Buffer) SetDeterministic(deterministic bool) {
b.deterministic = deterministic
}
// SetBuf sets buf as the internal buffer,
// where the contents of buf are considered the unread portion of the buffer.
func (b *Buffer) SetBuf(buf []byte) {
b.buf = buf
b.idx = 0
}
// Reset clears the internal buffer of all written and unread data.
func (b *Buffer) Reset() {
b.buf = b.buf[:0]
b.idx = 0
}
// Bytes returns the internal buffer.
func (b *Buffer) Bytes() []byte {
return b.buf
}
// Unread returns the unread portion of the buffer.
func (b *Buffer) Unread() []byte {
return b.buf[b.idx:]
}
// Marshal appends the wire-format encoding of m to the buffer.
func (b *Buffer) Marshal(m Message) error {
var err error
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
return err
}
// Unmarshal parses the wire-format message in the buffer and places the decoded results in m.
//
// Unlike proto.Unmarshal, this does not reset the message before starting to unmarshal.
func (b *Buffer) Unmarshal(m Message) error {
err := UnmarshalMerge(b.Unread(), m)
b.idx = len(b.buf)
return err
}
type unknownFields struct{ XXX_unrecognized protoimpl.UnknownFields }
func (m *unknownFields) String() string { panic("not implemented") }
func (m *unknownFields) Reset() { panic("not implemented") }
func (m *unknownFields) ProtoMessage() { panic("not implemented") }
// DebugPrint dumps the encoded bytes of b with a header and footer including s
// to stdout. This is only intended for debugging.
func (*Buffer) DebugPrint(s string, b []byte) {
m := protoimpl.X.MessageOf(new(unknownFields))
m.SetUnknown(b)
b, _ = prototext.MarshalOptions{AllowPartial: true, Indent: "\t"}.Marshal(m.Interface())
fmt.Printf("==== %s ====\n%s==== %s ====\n", s, b, s)
}
// EncodeVarint appends an unsigned varint encoding to the buffer.
func (b *Buffer) EncodeVarint(v uint64) error {
b.buf = wire.AppendVarint(b.buf, v)
return nil
}
// EncodeZigzag32 appends a 32-bit zig-zag varint encoding to the buffer.
func (b *Buffer) EncodeZigzag32(v uint64) error {
return b.EncodeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
}
// EncodeZigzag64 appends a 64-bit zig-zag varint encoding to the buffer.
func (b *Buffer) EncodeZigzag64(v uint64) error {
return b.EncodeVarint(uint64((uint64(v) << 1) ^ uint64((int64(v) >> 63))))
}
// EncodeFixed32 appends a 32-bit little-endian integer to the buffer.
func (b *Buffer) EncodeFixed32(v uint64) error {
b.buf = wire.AppendFixed32(b.buf, uint32(v))
return nil
}
// EncodeFixed64 appends a 64-bit little-endian integer to the buffer.
func (b *Buffer) EncodeFixed64(v uint64) error {
b.buf = wire.AppendFixed64(b.buf, uint64(v))
return nil
}
// EncodeRawBytes appends a length-prefixed raw bytes to the buffer.
func (b *Buffer) EncodeRawBytes(v []byte) error {
b.buf = wire.AppendBytes(b.buf, v)
return nil
}
// EncodeStringBytes appends a length-prefixed raw bytes to the buffer.
// It does not validate whether v contains valid UTF-8.
func (b *Buffer) EncodeStringBytes(v string) error {
b.buf = wire.AppendString(b.buf, v)
return nil
}
// EncodeMessage appends a length-prefixed encoded message to the buffer.
func (b *Buffer) EncodeMessage(m Message) error {
var err error
b.buf = wire.AppendVarint(b.buf, uint64(Size(m)))
b.buf, err = marshalAppend(b.buf, m, b.deterministic)
return err
}
// DecodeVarint consumes an encoded unsigned varint from the buffer.
func (b *Buffer) DecodeVarint() (uint64, error) {
v, n := wire.ConsumeVarint(b.buf[b.idx:])
if n < 0 {
return 0, wire.ParseError(n)
}
b.idx += n
return uint64(v), nil
}
// DecodeZigzag32 consumes an encoded 32-bit zig-zag varint from the buffer.
func (b *Buffer) DecodeZigzag32() (uint64, error) {
v, err := b.DecodeVarint()
if err != nil {
return 0, err
}
return uint64((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31)), nil
}
// DecodeZigzag64 consumes an encoded 64-bit zig-zag varint from the buffer.
func (b *Buffer) DecodeZigzag64() (uint64, error) {
v, err := b.DecodeVarint()
if err != nil {
return 0, err
}
return uint64((uint64(v) >> 1) ^ uint64((int64(v&1)<<63)>>63)), nil
}
// DecodeFixed32 consumes a 32-bit little-endian integer from the buffer.
func (b *Buffer) DecodeFixed32() (uint64, error) {
v, n := wire.ConsumeFixed32(b.buf[b.idx:])
if n < 0 {
return 0, wire.ParseError(n)
}
b.idx += n
return uint64(v), nil
}
// DecodeFixed64 consumes a 64-bit little-endian integer from the buffer.
func (b *Buffer) DecodeFixed64() (uint64, error) {
v, n := wire.ConsumeFixed64(b.buf[b.idx:])
if n < 0 {
return 0, wire.ParseError(n)
}
b.idx += n
return uint64(v), nil
}
// DecodeRawBytes consumes a length-prefixed raw bytes from the buffer.
// If alloc is specified, it returns a copy the raw bytes
// rather than a sub-slice of the buffer.
func (b *Buffer) DecodeRawBytes(alloc bool) ([]byte, error) {
v, n := wire.ConsumeBytes(b.buf[b.idx:])
if n < 0 {
return nil, wire.ParseError(n)
}
b.idx += n
if alloc {
v = append([]byte(nil), v...)
}
return v, nil
}
// DecodeStringBytes consumes a length-prefixed raw bytes from the buffer.
// It does not validate whether the raw bytes contain valid UTF-8.
func (b *Buffer) DecodeStringBytes() (string, error) {
v, n := wire.ConsumeString(b.buf[b.idx:])
if n < 0 {
return "", wire.ParseError(n)
}
b.idx += n
return v, nil
}
// DecodeMessage consumes a length-prefixed message from the buffer.
// It does not reset m.
func (b *Buffer) DecodeMessage(m Message) error {
v, err := b.DecodeRawBytes(false)
if err != nil {
return err
}
return UnmarshalMerge(v, m)
}
// DecodeGroup consumes a message group from the buffer.
// It assumes that the start group marker has already been consumed and
// consumes all bytes until (and including the end group marker).
// It does not reset m.
func (b *Buffer) DecodeGroup(m Message) error {
v, n, err := consumeGroup(b.buf[b.idx:])
if err != nil {
return err
}
b.idx += n
return UnmarshalMerge(v, m)
}
// consumeGroup parses b until it finds an end group marker, returning
// the raw bytes of the message (excluding the end group marker) and the
// the total length of the message (including the end group marker).
func consumeGroup(b []byte) ([]byte, int, error) {
b0 := b
depth := 1 // assume this follows a start group marker
for {
_, wtyp, tagLen := wire.ConsumeTag(b)
if tagLen < 0 {
return nil, 0, wire.ParseError(tagLen)
}
b = b[tagLen:]
var valLen int
switch wtyp {
case wire.VarintType:
_, valLen = wire.ConsumeVarint(b)
case wire.Fixed32Type:
_, valLen = wire.ConsumeFixed32(b)
case wire.Fixed64Type:
_, valLen = wire.ConsumeFixed64(b)
case wire.BytesType:
_, valLen = wire.ConsumeBytes(b)
case wire.StartGroupType:
depth++
case wire.EndGroupType:
depth--
default:
return nil, 0, errors.New("proto: cannot parse reserved wire type")
}
if valLen < 0 {
return nil, 0, wire.ParseError(valLen)
}
b = b[valLen:]
if depth == 0 {
return b0[:len(b0)-len(b)-tagLen], len(b0) - len(b), nil
}
}
}

Просмотреть файл

@ -1,222 +0,0 @@
// Copyright 2011 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.
// Protocol buffer deep copy and merge.
// TODO: RawMessage.
package proto
import (
"fmt"
"log"
"reflect"
"strings"
"google.golang.org/protobuf/reflect/protoreflect"
)
// Clone returns a deep copy of a protocol buffer.
func Clone(src Message) Message {
in := reflect.ValueOf(src)
if in.IsNil() {
return src
}
out := reflect.New(in.Type().Elem())
dst := out.Interface().(Message)
Merge(dst, src)
return dst
}
// Merger is the interface representing objects that can merge messages of the same type.
type Merger interface {
// Merge merges src into this message.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
//
// Merge may panic if called with a different argument type than the receiver.
Merge(src Message)
}
// generatedMerger is the custom merge method that generated protos will have.
// We must add this method since a generate Merge method will conflict with
// many existing protos that have a Merge data field already defined.
type generatedMerger interface {
XXX_Merge(src Message)
}
// Merge merges src into dst.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
// Merge panics if src and dst are not the same type, or if dst is nil.
func Merge(dst, src Message) {
if m, ok := dst.(Merger); ok {
m.Merge(src)
return
}
in := reflect.ValueOf(src)
out := reflect.ValueOf(dst)
if out.IsNil() {
panic("proto: nil destination")
}
if in.Type() != out.Type() {
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
}
if in.IsNil() {
return // Merge from nil src is a noop
}
if m, ok := dst.(generatedMerger); ok {
m.XXX_Merge(src)
return
}
mergeStruct(out.Elem(), in.Elem())
}
func mergeStruct(out, in reflect.Value) {
sprop := GetProperties(in.Type())
for i := 0; i < in.NumField(); i++ {
f := in.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
}
if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
if emIn != nil {
mergeExtension(emOut, emIn)
}
}
uf := unknownFieldsValue(in)
if !uf.IsValid() {
return
}
uin := uf.Bytes()
if len(uin) > 0 {
unknownFieldsValue(out).SetBytes(append([]byte(nil), uin...))
}
}
// mergeAny performs a merge between two values of the same type.
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
// prop is set if this is a struct field (it may be nil).
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
if in.Type() == protoMessageType {
if !in.IsNil() {
if out.IsNil() {
out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
} else {
Merge(out.Interface().(Message), in.Interface().(Message))
}
}
return
}
switch in.Kind() {
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
reflect.String, reflect.Uint32, reflect.Uint64:
if !viaPtr && isProto3Zero(in) {
return
}
out.Set(in)
case reflect.Interface:
// Probably a oneof field; copy non-nil values.
if in.IsNil() {
return
}
// Allocate destination if it is not set, or set to a different type.
// Otherwise we will merge as normal.
if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
}
mergeAny(out.Elem(), in.Elem(), false, nil)
case reflect.Map:
if in.Len() == 0 {
return
}
if out.IsNil() {
out.Set(reflect.MakeMap(in.Type()))
}
// For maps with value types of *T or []byte we need to deep copy each value.
elemKind := in.Type().Elem().Kind()
for _, key := range in.MapKeys() {
var val reflect.Value
switch elemKind {
case reflect.Ptr:
val = reflect.New(in.Type().Elem().Elem())
mergeAny(val, in.MapIndex(key), false, nil)
case reflect.Slice:
val = in.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
default:
val = in.MapIndex(key)
}
out.SetMapIndex(key, val)
}
case reflect.Ptr:
if in.IsNil() {
return
}
if out.IsNil() {
out.Set(reflect.New(in.Elem().Type()))
}
mergeAny(out.Elem(), in.Elem(), true, nil)
case reflect.Slice:
if in.IsNil() {
return
}
if in.Type().Elem().Kind() == reflect.Uint8 {
// []byte is a scalar bytes field, not a repeated field.
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value, and should not
// be merged.
if prop != nil && prop.Proto3 && in.Len() == 0 {
return
}
// Make a deep copy.
// Append to []byte{} instead of []byte(nil) so that we never end up
// with a nil result.
out.SetBytes(append([]byte{}, in.Bytes()...))
return
}
n := in.Len()
if out.IsNil() {
out.Set(reflect.MakeSlice(in.Type(), 0, n))
}
switch in.Type().Elem().Kind() {
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
reflect.String, reflect.Uint32, reflect.Uint64:
out.Set(reflect.AppendSlice(out, in))
default:
for i := 0; i < n; i++ {
x := reflect.Indirect(reflect.New(in.Type().Elem()))
mergeAny(x, in.Index(i), false, nil)
out.Set(reflect.Append(out, x))
}
}
case reflect.Struct:
mergeStruct(out, in)
default:
// unknown type, so not a protocol buffer
log.Printf("proto: don't know how to copy %v", in)
}
}
func mergeExtension(out, in *extensionMap) {
in.Range(func(extNum protoreflect.FieldNumber, eIn Extension) bool {
var eOut Extension
eOut.SetType(eIn.GetType())
if eIn.HasValue() {
v := reflect.New(reflect.TypeOf(eIn.GetValue())).Elem()
mergeAny(v, reflect.ValueOf(eIn.GetValue()), false, nil)
eOut.SetEagerValue(v.Interface())
}
out.Set(extNum, eOut)
return true
})
}

Просмотреть файл

@ -1,396 +0,0 @@
// Copyright 2010 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.
package proto
/*
* Routines for decoding protocol buffer data to construct in-memory representations.
*/
import (
"errors"
"fmt"
"io"
)
// errOverflow is returned when an integer is too large to be represented.
var errOverflow = errors.New("proto: integer overflow")
// DecodeVarint reads a varint-encoded integer from the slice.
// It returns the integer and the number of bytes consumed, or
// zero if there is not enough.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func DecodeVarint(buf []byte) (x uint64, n int) {
for shift := uint(0); shift < 64; shift += 7 {
if n >= len(buf) {
return 0, 0
}
b := uint64(buf[n])
n++
x |= (b & 0x7F) << shift
if (b & 0x80) == 0 {
return x, n
}
}
// The number is too large to represent in a 64-bit value.
return 0, 0
}
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
i := p.index
l := len(p.buf)
for shift := uint(0); shift < 64; shift += 7 {
if i >= l {
err = io.ErrUnexpectedEOF
return
}
b := p.buf[i]
i++
x |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
p.index = i
return
}
}
// The number is too large to represent in a 64-bit value.
err = errOverflow
return
}
// DecodeVarint reads a varint-encoded integer from the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) DecodeVarint() (x uint64, err error) {
i := p.index
buf := p.buf
if i >= len(buf) {
return 0, io.ErrUnexpectedEOF
} else if buf[i] < 0x80 {
p.index++
return uint64(buf[i]), nil
} else if len(buf)-i < 10 {
return p.decodeVarintSlow()
}
var b uint64
// we already checked the first byte
x = uint64(buf[i]) - 0x80
i++
b = uint64(buf[i])
i++
x += b << 7
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 7
b = uint64(buf[i])
i++
x += b << 14
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 14
b = uint64(buf[i])
i++
x += b << 21
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 21
b = uint64(buf[i])
i++
x += b << 28
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 28
b = uint64(buf[i])
i++
x += b << 35
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 35
b = uint64(buf[i])
i++
x += b << 42
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 42
b = uint64(buf[i])
i++
x += b << 49
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 49
b = uint64(buf[i])
i++
x += b << 56
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 56
b = uint64(buf[i])
i++
x += b << 63
if b&0x80 == 0 {
goto done
}
return 0, errOverflow
done:
p.index = i
return x, nil
}
// DecodeFixed64 reads a 64-bit integer from the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) DecodeFixed64() (x uint64, err error) {
// x, err already 0
i := p.index + 8
if i < 0 || i > len(p.buf) {
err = io.ErrUnexpectedEOF
return
}
p.index = i
x = uint64(p.buf[i-8])
x |= uint64(p.buf[i-7]) << 8
x |= uint64(p.buf[i-6]) << 16
x |= uint64(p.buf[i-5]) << 24
x |= uint64(p.buf[i-4]) << 32
x |= uint64(p.buf[i-3]) << 40
x |= uint64(p.buf[i-2]) << 48
x |= uint64(p.buf[i-1]) << 56
return
}
// DecodeFixed32 reads a 32-bit integer from the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) DecodeFixed32() (x uint64, err error) {
// x, err already 0
i := p.index + 4
if i < 0 || i > len(p.buf) {
err = io.ErrUnexpectedEOF
return
}
p.index = i
x = uint64(p.buf[i-4])
x |= uint64(p.buf[i-3]) << 8
x |= uint64(p.buf[i-2]) << 16
x |= uint64(p.buf[i-1]) << 24
return
}
// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
// from the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
x, err = p.DecodeVarint()
if err != nil {
return
}
x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
return
}
// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
// from the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
x, err = p.DecodeVarint()
if err != nil {
return
}
x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
return
}
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
n, err := p.DecodeVarint()
if err != nil {
return nil, err
}
nb := int(n)
if nb < 0 {
return nil, fmt.Errorf("proto: bad byte length %d", nb)
}
end := p.index + nb
if end < p.index || end > len(p.buf) {
return nil, io.ErrUnexpectedEOF
}
if !alloc {
// todo: check if can get more uses of alloc=false
buf = p.buf[p.index:end]
p.index += nb
return
}
buf = make([]byte, nb)
copy(buf, p.buf[p.index:])
p.index += nb
return
}
// DecodeStringBytes reads an encoded string from the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) DecodeStringBytes() (s string, err error) {
buf, err := p.DecodeRawBytes(false)
if err != nil {
return
}
return string(buf), nil
}
// Unmarshaler is the interface representing objects that can
// unmarshal themselves. The argument points to data that may be
// overwritten, so implementations should not keep references to the
// buffer.
// Unmarshal implementations should not clear the receiver.
// Any unmarshaled data should be merged into the receiver.
// Callers of Unmarshal that do not want to retain existing data
// should Reset the receiver before calling Unmarshal.
type Unmarshaler interface {
Unmarshal([]byte) error
}
// newUnmarshaler is the interface representing objects that can
// unmarshal themselves. The semantics are identical to Unmarshaler.
//
// This exists to support protoc-gen-go generated messages.
// The proto package will stop type-asserting to this interface in the future.
//
// DO NOT DEPEND ON THIS.
type newUnmarshaler interface {
XXX_Unmarshal([]byte) error
}
// Unmarshal parses the protocol buffer representation in buf and places the
// decoded result in pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
//
// Unmarshal resets pb before starting to unmarshal, so any
// existing data in pb is always removed. Use UnmarshalMerge
// to preserve and append to existing data.
func Unmarshal(buf []byte, pb Message) error {
pb.Reset()
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
}
// UnmarshalMerge parses the protocol buffer representation in buf and
// writes the decoded result to pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
//
// UnmarshalMerge merges into existing data in pb.
// Most code should use Unmarshal instead.
func UnmarshalMerge(buf []byte, pb Message) error {
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
}
// DecodeMessage reads a count-delimited message from the Buffer.
func (p *Buffer) DecodeMessage(pb Message) error {
enc, err := p.DecodeRawBytes(false)
if err != nil {
return err
}
return NewBuffer(enc).Unmarshal(pb)
}
// DecodeGroup reads a tag-delimited group from the Buffer.
// StartGroup tag is already consumed. This function consumes
// EndGroup tag.
func (p *Buffer) DecodeGroup(pb Message) error {
b := p.buf[p.index:]
x, y := findEndGroup(b)
if x < 0 {
return io.ErrUnexpectedEOF
}
err := Unmarshal(b[:x], pb)
p.index += y
return err
}
// Unmarshal parses the protocol buffer representation in the
// Buffer and places the decoded result in pb. If the struct
// underlying pb does not match the data in the buffer, the results can be
// unpredictable.
//
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
func (p *Buffer) Unmarshal(pb Message) error {
// If the object can unmarshal itself, let it.
if u, ok := pb.(newUnmarshaler); ok {
err := u.XXX_Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
err := u.Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
// Slow workaround for messages that aren't Unmarshalers.
// This includes some hand-coded .pb.go files and
// bootstrap protos.
// TODO: fix all of those and then add Unmarshal to
// the Message interface. Then:
// The cast above and code below can be deleted.
// The old unmarshaler can be deleted.
// Clients can call Unmarshal directly (can already do that, actually).
var info InternalMessageInfo
err := info.Unmarshal(pb, p.buf[p.index:])
p.index = len(p.buf)
return err
}

64
proto/defaults.go Normal file
Просмотреть файл

@ -0,0 +1,64 @@
// 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.
package proto
import (
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
)
// SetDefaults sets unpopulated scalar fields to their default values.
// Fields within a oneof are not set even if they have a default value.
// SetDefaults is recursively called upon any populated message fields.
func SetDefaults(m Message) {
if m != nil {
setDefaults(protoimpl.X.MessageOf(m))
}
}
func setDefaults(m protoreflect.Message) {
fds := m.Descriptor().Fields()
for i := 0; i < fds.Len(); i++ {
fd := fds.Get(i)
if !m.Has(fd) {
if fd.HasDefault() && fd.ContainingOneof() == nil {
v := fd.Default()
if fd.Kind() == protoreflect.BytesKind {
v = protoreflect.ValueOf(append([]byte(nil), v.Bytes()...)) // copy the default bytes
}
m.Set(fd, v)
}
continue
}
}
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
switch {
// Handle singular message.
case fd.Cardinality() != protoreflect.Repeated:
if fd.Message() != nil {
setDefaults(m.Get(fd).Message())
}
// Handle list of messages.
case fd.IsList():
if fd.Message() != nil {
ls := m.Get(fd).List()
for i := 0; i < ls.Len(); i++ {
setDefaults(ls.Get(i).Message())
}
}
// Handle map of messages.
case fd.IsMap():
if fd.MapValue().Message() != nil {
ms := m.Get(fd).Map()
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
setDefaults(v.Message())
return true
})
}
}
return true
})
}

Просмотреть файл

@ -12,7 +12,22 @@ import (
)
// Deprecated: Do not use.
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
const (
ProtoPackageIsVersion1 = true
ProtoPackageIsVersion2 = true
ProtoPackageIsVersion3 = true
)
var (
// Deprecated: No longer returned.
ErrNil = errors.New("proto: Marshal called with nil")
// Deprecated: No longer returned.
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
// Deprecated: No longer returned.
ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
)
// Deprecated: Do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
@ -45,29 +60,40 @@ func RegisterMessageSetType(Message, int32, string) {}
// Deprecated: Do not use.
func EnumName(m map[int32]string, v int32) string {
if s, ok := m[v]; ok {
s, ok := m[v]
if ok {
return s
}
return strconv.Itoa(int(v))
}
// Deprecated: Do not use.
func UnmarshalJSONEnum(m map[string]int32, b []byte, enumName string) (int32, error) {
if b[0] == '"' {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return 0, fmt.Errorf("proto: invalid input for enum %v: %s", enumName, b)
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
if data[0] == '"' {
// New style: enums are strings.
var repr string
if err := json.Unmarshal(data, &repr); err != nil {
return -1, err
}
v, ok := m[s]
val, ok := m[repr]
if !ok {
return 0, fmt.Errorf("proto: invalid value for enum %v: %s", enumName, b)
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
}
return v, nil
} else {
var v int32
if err := json.Unmarshal(b, &v); err != nil {
return 0, fmt.Errorf("proto: invalid input for enum %v: %s", enumName, b)
}
return v, nil
return val, nil
}
// Old style: enums are ints.
var val int32
if err := json.Unmarshal(data, &val); err != nil {
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
}
return val, nil
}
// Deprecated: Do not use.
type InternalMessageInfo struct{}
func (*InternalMessageInfo) DiscardUnknown(Message) { panic("not implemented") }
func (*InternalMessageInfo) Marshal([]byte, Message, bool) ([]byte, error) { panic("not implemented") }
func (*InternalMessageInfo) Merge(Message, Message) { panic("not implemented") }
func (*InternalMessageInfo) Size(Message) int { panic("not implemented") }
func (*InternalMessageInfo) Unmarshal(Message, []byte) error { panic("not implemented") }

Просмотреть файл

@ -1,23 +1,14 @@
// Copyright 2017 The Go Authors. All rights reserved.
// 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.
package proto
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
)
type generatedDiscarder interface {
XXX_DiscardUnknown()
}
// DiscardUnknown recursively discards all unknown fields from this message
// and all embedded messages.
//
@ -26,310 +17,43 @@ type generatedDiscarder interface {
// marshal to be able to produce a message that continues to have those
// unrecognized fields. To avoid this, DiscardUnknown is used to
// explicitly clear the unknown fields after unmarshaling.
//
// For proto2 messages, the unknown fields of message extensions are only
// discarded from messages that have been accessed via GetExtension.
func DiscardUnknown(m Message) {
if discardUnknownAlt != nil {
discardUnknownAlt(m) // populated by hooks_enabled.go
return
if m != nil {
discardUnknown(protoimpl.X.MessageOf(m))
}
if m, ok := m.(generatedDiscarder); ok {
m.XXX_DiscardUnknown()
return
}
// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
// but the master branch has no implementation for InternalMessageInfo,
// so it would be more work to replicate that approach.
discardLegacy(m)
}
// DiscardUnknown recursively discards all unknown fields.
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
di := atomicLoadDiscardInfo(&a.discard)
if di == nil {
di = getDiscardInfo(reflect.TypeOf(m).Elem())
atomicStoreDiscardInfo(&a.discard, di)
}
di.discard(toPointer(&m))
}
type discardInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []discardFieldInfo
unrecognized field
}
type discardFieldInfo struct {
field field // Offset of field, guaranteed to be valid
discard func(src pointer)
}
var (
discardInfoMap = map[reflect.Type]*discardInfo{}
discardInfoLock sync.Mutex
)
func getDiscardInfo(t reflect.Type) *discardInfo {
discardInfoLock.Lock()
defer discardInfoLock.Unlock()
di := discardInfoMap[t]
if di == nil {
di = &discardInfo{typ: t}
discardInfoMap[t] = di
}
return di
}
func (di *discardInfo) discard(src pointer) {
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&di.initialized) == 0 {
di.computeDiscardInfo()
}
for _, fi := range di.fields {
sfp := src.offset(fi.field)
fi.discard(sfp)
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
em.Range(func(_ protoreflect.FieldNumber, mx Extension) bool {
if m, ok := mx.GetValue().(Message); ok {
DiscardUnknown(m)
func discardUnknown(m protoreflect.Message) {
m.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool {
switch {
// Handle singular message.
case fd.Cardinality() != protoreflect.Repeated:
if fd.Message() != nil {
discardUnknown(m.Get(fd).Message())
}
return true
})
}
if di.unrecognized.IsValid() {
*src.offset(di.unrecognized).toBytes() = nil
}
}
func (di *discardInfo) computeDiscardInfo() {
di.lock.Lock()
defer di.lock.Unlock()
if di.initialized != 0 {
return
}
t := di.typ
n := t.NumField()
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
dfi := discardFieldInfo{field: toField(&f, nil)}
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
case isSlice: // E.g., []*pb.T
di := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sps := src.getPointerSlice()
for _, sp := range sps {
if !sp.isNil() {
di.discard(sp)
}
}
}
default: // E.g., *pb.T
di := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sp := src.getPointer()
if !sp.isNil() {
di.discard(sp)
}
// Handle list of messages.
case fd.IsList():
if fd.Message() != nil {
ls := m.Get(fd).List()
for i := 0; i < ls.Len(); i++ {
discardUnknown(ls.Get(i).Message())
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
default: // E.g., map[K]V
if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
dfi.discard = func(src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
DiscardUnknown(val.Interface().(Message))
}
}
} else {
dfi.discard = func(pointer) {} // Noop
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
default: // E.g., interface{}
// TODO: Make this faster?
dfi.discard = func(src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
DiscardUnknown(sv.Interface().(Message))
}
}
}
}
default:
continue
}
di.fields = append(di.fields, dfi)
}
expFunc := exporterFunc(t)
di.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
di.unrecognized = toField(&f, nil)
}
if f, ok := t.FieldByName("unknownFields"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected unknownFields to be of type []byte")
}
di.unrecognized = toField(&f, expFunc)
}
atomic.StoreInt32(&di.initialized, 1)
}
func discardLegacy(m Message) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Ptr || v.IsNil() {
return
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
vf := v.Field(i)
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
case isSlice: // E.g., []*pb.T
for j := 0; j < vf.Len(); j++ {
discardLegacy(vf.Index(j).Interface().(Message))
}
default: // E.g., *pb.T
discardLegacy(vf.Interface().(Message))
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
default: // E.g., map[K]V
tv := vf.Type().Elem()
if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
for _, key := range vf.MapKeys() {
val := vf.MapIndex(key)
discardLegacy(val.Interface().(Message))
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
default: // E.g., test_proto.isCommunique_Union interface
if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
vf = vf.Elem() // E.g., *test_proto.Communique_Msg
if !vf.IsNil() {
vf = vf.Elem() // E.g., test_proto.Communique_Msg
vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
if vf.Kind() == reflect.Ptr {
discardLegacy(vf.Interface().(Message))
}
}
}
// Handle map of messages.
case fd.IsMap():
if fd.MapValue().Message() != nil {
ms := m.Get(fd).Map()
ms.Range(func(_ protoreflect.MapKey, v protoreflect.Value) bool {
discardUnknown(v.Message())
return true
})
}
}
}
return true
})
if vf := unknownFieldsValue(v); vf.IsValid() {
if vf.Type() != reflect.TypeOf([]byte{}) {
panic("expected unknown fields to be of type []byte")
}
vf.Set(reflect.ValueOf([]byte(nil)))
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, err := extendable(m); err == nil {
em.Range(func(_ protoreflect.FieldNumber, mx Extension) bool {
if m, ok := mx.GetValue().(Message); ok {
discardLegacy(m)
}
return true
})
// Discard unknown fields.
if len(m.GetUnknown()) > 0 {
m.SetUnknown(nil)
}
}

Просмотреть файл

@ -9,8 +9,8 @@ import (
"github.com/golang/protobuf/proto"
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
pb "github.com/golang/protobuf/proto/test_proto"
pb2 "github.com/golang/protobuf/internal/testprotos/proto2_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
const rawFields = "\x2d\xc3\xd2\xe1\xf0"
@ -24,81 +24,81 @@ func TestDiscardUnknown(t *testing.T) {
in: nil, want: nil, // Should not panic
}, {
desc: "NilPtr",
in: (*proto3pb.Message)(nil), want: (*proto3pb.Message)(nil), // Should not panic
in: (*pb3.Message)(nil), want: (*pb3.Message)(nil), // Should not panic
}, {
desc: "Nested",
in: &proto3pb.Message{
in: &pb3.Message{
Name: "Aaron",
Nested: &proto3pb.Nested{Cute: true, XXX_unrecognized: []byte(rawFields)},
Nested: &pb3.Nested{Cute: true, XXX_unrecognized: []byte(rawFields)},
XXX_unrecognized: []byte(rawFields),
},
want: &proto3pb.Message{
want: &pb3.Message{
Name: "Aaron",
Nested: &proto3pb.Nested{Cute: true},
Nested: &pb3.Nested{Cute: true},
},
}, {
desc: "Slice",
in: &proto3pb.Message{
in: &pb3.Message{
Name: "Aaron",
Children: []*proto3pb.Message{
Children: []*pb3.Message{
{Name: "Sarah", XXX_unrecognized: []byte(rawFields)},
{Name: "Abraham", XXX_unrecognized: []byte(rawFields)},
},
XXX_unrecognized: []byte(rawFields),
},
want: &proto3pb.Message{
want: &pb3.Message{
Name: "Aaron",
Children: []*proto3pb.Message{
Children: []*pb3.Message{
{Name: "Sarah"},
{Name: "Abraham"},
},
},
}, {
desc: "OneOf",
in: &pb.Communique{
Union: &pb.Communique_Msg{&pb.Strings{
in: &pb2.Communique{
Union: &pb2.Communique_Msg{&pb2.Strings{
StringField: proto.String("123"),
XXX_unrecognized: []byte(rawFields),
}},
XXX_unrecognized: []byte(rawFields),
},
want: &pb.Communique{
Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123")}},
want: &pb2.Communique{
Union: &pb2.Communique_Msg{&pb2.Strings{StringField: proto.String("123")}},
},
}, {
desc: "Map",
in: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: &pb.FloatingPoint{
in: &pb2.MessageWithMap{MsgMapping: map[int64]*pb2.FloatingPoint{
0x4002: &pb2.FloatingPoint{
Exact: proto.Bool(true),
XXX_unrecognized: []byte(rawFields),
},
}},
want: &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: &pb.FloatingPoint{Exact: proto.Bool(true)},
want: &pb2.MessageWithMap{MsgMapping: map[int64]*pb2.FloatingPoint{
0x4002: &pb2.FloatingPoint{Exact: proto.Bool(true)},
}},
}, {
desc: "Extension",
in: func() proto.Message {
m := &pb.MyMessage{
m := &pb2.MyMessage{
Count: proto.Int32(42),
Somegroup: &pb.MyMessage_SomeGroup{
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(6),
XXX_unrecognized: []byte(rawFields),
},
XXX_unrecognized: []byte(rawFields),
}
proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{
proto.SetExtension(m, pb2.E_Ext_More, &pb2.Ext{
Data: proto.String("extension"),
XXX_unrecognized: []byte(rawFields),
})
return m
}(),
want: func() proto.Message {
m := &pb.MyMessage{
m := &pb2.MyMessage{
Count: proto.Int32(42),
Somegroup: &pb.MyMessage_SomeGroup{GroupField: proto.Int32(6)},
Somegroup: &pb2.MyMessage_SomeGroup{GroupField: proto.Int32(6)},
}
proto.SetExtension(m, pb.E_Ext_More, &pb.Ext{Data: proto.String("extension")})
proto.SetExtension(m, pb2.E_Ext_More, &pb2.Ext{Data: proto.String("extension")})
return m
}(),
}}

Просмотреть файл

@ -1,176 +0,0 @@
// Copyright 2010 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.
package proto
/*
* Routines for encoding data into the wire format for protocol buffers.
*/
import (
"errors"
"reflect"
)
var (
// errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element.
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
// errOneofHasNil is the error returned if Marshal is called with
// a struct with a oneof field containing a nil element.
errOneofHasNil = errors.New("proto: oneof field has nil value")
// ErrNil is the error returned if Marshal is called with nil.
ErrNil = errors.New("proto: Marshal called with nil")
// ErrTooLarge is the error returned if Marshal is called with a
// message that encodes to >2GB.
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
)
// The fundamental encoders that put bytes on the wire.
// Those that take integer types all accept uint64 and are
// therefore of type valueEncoder.
const maxVarintBytes = 10 // maximum length of a varint
// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
// Not used by the package itself, but helpful to clients
// wishing to use the same encoding.
func EncodeVarint(x uint64) []byte {
var buf [maxVarintBytes]byte
var n int
for n = 0; x > 127; n++ {
buf[n] = 0x80 | uint8(x&0x7F)
x >>= 7
}
buf[n] = uint8(x)
n++
return buf[0:n]
}
// EncodeVarint writes a varint-encoded integer to the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) EncodeVarint(x uint64) error {
for x >= 1<<7 {
p.buf = append(p.buf, uint8(x&0x7f|0x80))
x >>= 7
}
p.buf = append(p.buf, uint8(x))
return nil
}
// SizeVarint returns the varint encoding size of an integer.
func SizeVarint(x uint64) int {
switch {
case x < 1<<7:
return 1
case x < 1<<14:
return 2
case x < 1<<21:
return 3
case x < 1<<28:
return 4
case x < 1<<35:
return 5
case x < 1<<42:
return 6
case x < 1<<49:
return 7
case x < 1<<56:
return 8
case x < 1<<63:
return 9
}
return 10
}
// EncodeFixed64 writes a 64-bit integer to the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) EncodeFixed64(x uint64) error {
p.buf = append(p.buf,
uint8(x),
uint8(x>>8),
uint8(x>>16),
uint8(x>>24),
uint8(x>>32),
uint8(x>>40),
uint8(x>>48),
uint8(x>>56))
return nil
}
// EncodeFixed32 writes a 32-bit integer to the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) EncodeFixed32(x uint64) error {
p.buf = append(p.buf,
uint8(x),
uint8(x>>8),
uint8(x>>16),
uint8(x>>24))
return nil
}
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
// to the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) EncodeZigzag64(x uint64) error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
// to the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) EncodeZigzag32(x uint64) error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
func (p *Buffer) EncodeRawBytes(b []byte) error {
p.EncodeVarint(uint64(len(b)))
p.buf = append(p.buf, b...)
return nil
}
// EncodeStringBytes writes an encoded string to the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) EncodeStringBytes(s string) error {
p.EncodeVarint(uint64(len(s)))
p.buf = append(p.buf, s...)
return nil
}
// Marshaler is the interface representing objects that can marshal themselves.
type Marshaler interface {
Marshal() ([]byte, error)
}
// EncodeMessage writes the protocol buffer to the Buffer,
// prefixed by a varint-encoded length.
func (p *Buffer) EncodeMessage(pb Message) error {
siz := Size(pb)
p.EncodeVarint(uint64(siz))
return p.Marshal(pb)
}
// All protocol buffer fields are nillable, but be careful.
func isNil(v reflect.Value) bool {
switch v.Kind() {
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return v.IsNil()
}
return false
}

Просмотреть файл

@ -1,235 +0,0 @@
// Copyright 2011 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.
// Protocol buffer comparison.
package proto
import (
"bytes"
"log"
"reflect"
"strings"
"google.golang.org/protobuf/reflect/protoreflect"
)
/*
Equal returns true iff protocol buffers a and b are equal.
The arguments must both be pointers to protocol buffer structs.
Equality is defined in this way:
- Two messages are equal iff they are the same type,
corresponding fields are equal, unknown field sets
are equal, and extensions sets are equal.
- Two set scalar fields are equal iff their values are equal.
If the fields are of a floating-point type, remember that
NaN != x for all x, including NaN. If the message is defined
in a proto3 .proto file, fields are not "set"; specifically,
zero length proto3 "bytes" fields are equal (nil == {}).
- Two repeated fields are equal iff their lengths are the same,
and their corresponding elements are equal. Note a "bytes" field,
although represented by []byte, is not a repeated field and the
rule for the scalar fields described above applies.
- Two unset fields are equal.
- Two unknown field sets are equal if their current
encoded state is equal.
- Two extension sets are equal iff they have corresponding
elements that are pairwise equal.
- Two map fields are equal iff their lengths are the same,
and they contain the same set of elements. Zero-length map
fields are equal.
- Every other combination of things are not equal.
The return value is undefined if a and b are not protocol buffers.
*/
func Equal(a, b Message) bool {
if a == nil || b == nil {
return a == b
}
v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
if v1.Type() != v2.Type() {
return false
}
if v1.Kind() == reflect.Ptr {
if v1.IsNil() {
return v2.IsNil()
}
if v2.IsNil() {
return false
}
v1, v2 = v1.Elem(), v2.Elem()
}
if v1.Kind() != reflect.Struct {
return false
}
return equalStruct(v1, v2)
}
// v1 and v2 are known to have the same type.
func equalStruct(v1, v2 reflect.Value) bool {
sprop := GetProperties(v1.Type())
for i := 0; i < v1.NumField(); i++ {
f := v1.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
f1, f2 := v1.Field(i), v2.Field(i)
if f.Type.Kind() == reflect.Ptr {
if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
// both unset
continue
} else if n1 != n2 {
// set/unset mismatch
return false
}
f1, f2 = f1.Elem(), f2.Elem()
}
if !equalAny(f1, f2, sprop.Prop[i]) {
return false
}
}
if em1 := extensionFieldsValue(v1); em1.IsValid() {
em2 := extensionFieldsValue(v2)
m1 := extensionFieldsOf(em1.Addr().Interface())
m2 := extensionFieldsOf(em2.Addr().Interface())
if !equalExtensions(v1.Type(), m1, m2) {
return false
}
}
if uf := unknownFieldsValue(v1); uf.IsValid() {
u1 := uf.Bytes()
u2 := unknownFieldsValue(v2).Bytes()
if !bytes.Equal(u1, u2) {
return false
}
}
return true
}
// v1 and v2 are known to have the same type.
// prop may be nil.
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
if v1.Type() == protoMessageType {
m1, _ := v1.Interface().(Message)
m2, _ := v2.Interface().(Message)
return Equal(m1, m2)
}
switch v1.Kind() {
case reflect.Bool:
return v1.Bool() == v2.Bool()
case reflect.Float32, reflect.Float64:
return v1.Float() == v2.Float()
case reflect.Int32, reflect.Int64:
return v1.Int() == v2.Int()
case reflect.Interface:
// Probably a oneof field; compare the inner values.
n1, n2 := v1.IsNil(), v2.IsNil()
if n1 || n2 {
return n1 == n2
}
e1, e2 := v1.Elem(), v2.Elem()
if e1.Type() != e2.Type() {
return false
}
return equalAny(e1, e2, nil)
case reflect.Map:
if v1.Len() != v2.Len() {
return false
}
for _, key := range v1.MapKeys() {
val2 := v2.MapIndex(key)
if !val2.IsValid() {
// This key was not found in the second map.
return false
}
if !equalAny(v1.MapIndex(key), val2, nil) {
return false
}
}
return true
case reflect.Ptr:
// Maps may have nil values in them, so check for nil.
if v1.IsNil() && v2.IsNil() {
return true
}
if v1.IsNil() != v2.IsNil() {
return false
}
return equalAny(v1.Elem(), v2.Elem(), prop)
case reflect.Slice:
if v1.Type().Elem().Kind() == reflect.Uint8 {
// short circuit: []byte
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value.
if prop != nil && prop.Proto3 && v1.Len() == 0 && v2.Len() == 0 {
return true
}
if v1.IsNil() != v2.IsNil() {
return false
}
return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
}
if v1.Len() != v2.Len() {
return false
}
for i := 0; i < v1.Len(); i++ {
if !equalAny(v1.Index(i), v2.Index(i), prop) {
return false
}
}
return true
case reflect.String:
return v1.Interface().(string) == v2.Interface().(string)
case reflect.Struct:
return equalStruct(v1, v2)
case reflect.Uint32, reflect.Uint64:
return v1.Uint() == v2.Uint()
}
// unknown type, so not a protocol buffer
log.Printf("proto: don't know how to compare %v", v1)
return false
}
func equalExtensions(base reflect.Type, em1, em2 *extensionMap) bool {
if em1.Len() != em2.Len() {
return false
}
equal := true
em1.Range(func(extNum protoreflect.FieldNumber, e1 Extension) bool {
if !em2.Has(extNum) {
equal = false
return false
}
e2 := em2.Get(extNum)
m1 := extensionAsLegacyType(e1.GetValue())
m2 := extensionAsLegacyType(e2.GetValue())
if m1 == nil && m2 == nil {
return true
}
if m1 != nil && m2 != nil {
// Both are unencoded.
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
equal = false
return false
}
return true
}
equal = false
return false
})
return equal
}

Просмотреть файл

@ -1,217 +0,0 @@
// Copyright 2011 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.
package proto_test
import (
"testing"
. "github.com/golang/protobuf/proto"
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
pb "github.com/golang/protobuf/proto/test_proto"
)
// Four identical base messages.
// The init function adds extensions to some of them.
var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3a = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3b = &pb.MyMessage{Count: Int32(7)}
var messageWithExtension3c = &pb.MyMessage{Count: Int32(7)}
// Two messages with non-message extensions.
var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)}
var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)}
func init() {
ext1 := &pb.Ext{Data: String("Kirk")}
ext2 := &pb.Ext{Data: String("Picard")}
// messageWithExtension1a has ext1, but never marshals it.
if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil {
panic("SetExtension on 1a failed: " + err.Error())
}
// messageWithExtension1b is the unmarshaled form of messageWithExtension1a.
if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil {
panic("SetExtension on 1b failed: " + err.Error())
}
buf, err := Marshal(messageWithExtension1b)
if err != nil {
panic("Marshal of 1b failed: " + err.Error())
}
messageWithExtension1b.Reset()
if err := Unmarshal(buf, messageWithExtension1b); err != nil {
panic("Unmarshal of 1b failed: " + err.Error())
}
// messageWithExtension2 has ext2.
if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil {
panic("SetExtension on 2 failed: " + err.Error())
}
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil {
panic("SetExtension on Int32-1 failed: " + err.Error())
}
if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil {
panic("SetExtension on Int32-2 failed: " + err.Error())
}
// messageWithExtension3{a,b,c} has unregistered extension.
if RegisteredExtensions(messageWithExtension3a)[200] != nil {
panic("expect extension 200 unregistered")
}
bytes := []byte{
0xc0, 0x0c, 0x01, // id=200, wiretype=0 (varint), data=1
}
bytes2 := []byte{
0xc0, 0x0c, 0x02, // id=200, wiretype=0 (varint), data=2
}
SetRawExtension(messageWithExtension3a, 200, bytes)
SetRawExtension(messageWithExtension3b, 200, bytes)
SetRawExtension(messageWithExtension3c, 200, bytes2)
}
var EqualTests = []struct {
desc string
a, b Message
exp bool
}{
{"different types", &pb.GoEnum{}, &pb.GoTestField{}, false},
{"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true},
{"nil vs nil", nil, nil, true},
{"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true},
{"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false},
{"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false},
{"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false},
{"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false},
{"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false},
{"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true},
{"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false},
{"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false},
{"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false},
{"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true},
{"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true},
{"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true},
{"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true},
{
"nested, different",
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}},
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}},
false,
},
{
"nested, equal",
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
&pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}},
true,
},
{"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true},
{"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true},
{"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false},
{
"repeated bytes",
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
&pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
true,
},
// In proto3, []byte{} and []byte(nil) are equal.
{"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true},
{"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
{"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
{"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false},
{"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true},
{"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false},
{"unregistered extension same", messageWithExtension3a, messageWithExtension3b, true},
{"unregistered extension different", messageWithExtension3a, messageWithExtension3c, false},
{
"message with group",
&pb.MyMessage{
Count: Int32(1),
Somegroup: &pb.MyMessage_SomeGroup{
GroupField: Int32(5),
},
},
&pb.MyMessage{
Count: Int32(1),
Somegroup: &pb.MyMessage_SomeGroup{
GroupField: Int32(5),
},
},
true,
},
{
"map same",
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
true,
},
{
"map different entry",
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}},
false,
},
{
"map different key only",
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}},
false,
},
{
"map different value only",
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
false,
},
{
"zero-length maps same",
&pb.MessageWithMap{NameMapping: map[int32]string{}},
&pb.MessageWithMap{NameMapping: nil},
true,
},
{
"orders in map don't matter",
&pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken", 2: "Rob"}},
&pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob", 1: "Ken"}},
true,
},
{
"oneof same",
&pb.Communique{Union: &pb.Communique_Number{41}},
&pb.Communique{Union: &pb.Communique_Number{41}},
true,
},
{
"oneof one nil",
&pb.Communique{Union: &pb.Communique_Number{41}},
&pb.Communique{},
false,
},
{
"oneof different",
&pb.Communique{Union: &pb.Communique_Number{41}},
&pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
false,
},
}
func TestEqual(t *testing.T) {
for _, tc := range EqualTests {
if res := Equal(tc.a, tc.b); res != tc.exp {
t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp)
}
}
}

Просмотреть файл

@ -4,227 +4,108 @@
package proto
/*
* Types and routines for supporting protocol buffer extensions.
*/
import (
"errors"
"fmt"
"io"
"reflect"
"sync"
"github.com/golang/protobuf/internal/wire"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoiface"
"google.golang.org/protobuf/runtime/protoimpl"
)
// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
var ErrMissingExtension = errors.New("proto: missing extension")
func extensionFieldsOf(p interface{}) *extensionMap {
if p, ok := p.(*map[int32]Extension); ok {
return (*extensionMap)(p)
}
panic(fmt.Sprintf("invalid extension fields type: %T", p))
}
type extensionMap map[int32]Extension
func (m extensionMap) Len() int {
return len(m)
}
func (m extensionMap) Has(n protoreflect.FieldNumber) bool {
_, ok := m[int32(n)]
return ok
}
func (m extensionMap) Get(n protoreflect.FieldNumber) Extension {
return m[int32(n)]
}
func (m *extensionMap) Set(n protoreflect.FieldNumber, x Extension) {
if *m == nil {
*m = make(map[int32]Extension)
}
(*m)[int32(n)] = x
}
func (m *extensionMap) Clear(n protoreflect.FieldNumber) {
delete(*m, int32(n))
}
func (m extensionMap) Range(f func(protoreflect.FieldNumber, Extension) bool) {
for n, x := range m {
if !f(protoreflect.FieldNumber(n), x) {
return
}
}
}
func extendable(p interface{}) (*extensionMap, error) {
type extendableProto interface {
Message
ExtensionRangeArray() []ExtensionRange
}
if _, ok := p.(extendableProto); ok {
v := reflect.ValueOf(p)
if v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
if vf := extensionFieldsValue(v); vf.IsValid() {
return extensionFieldsOf(vf.Addr().Interface()), nil
}
}
}
// Don't allocate a specific error containing %T:
// this is the hot path for Clone and MarshalText.
return nil, errNotExtendable
}
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
type (
ExtensionRange = protoiface.ExtensionRangeV1
ExtensionDesc = protoimpl.ExtensionInfo
Extension = protoimpl.ExtensionFieldV1
// ExtensionDesc represents an extension descriptor and
// is used to interact with an extension field in a message.
//
// Variables of this type are generated in code by protoc-gen-go.
ExtensionDesc = protoimpl.ExtensionInfo
// ExtensionRange represents a range of message extensions.
// Used in code generated by protoc-gen-go.
ExtensionRange = protoiface.ExtensionRangeV1
// Deprecated: Do not use; this is an internal type.
Extension = protoimpl.ExtensionFieldV1
// Deprecated: Do not use; this is an internal type.
XXX_InternalExtensions = protoimpl.ExtensionFields
)
func isRepeatedExtension(ed *ExtensionDesc) bool {
t := reflect.TypeOf(ed.ExtensionType)
return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
}
// ErrMissingExtension reports whether the extension was not present.
var ErrMissingExtension = errors.New("proto: missing extension")
// SetRawExtension is for testing only.
func SetRawExtension(base Message, id int32, b []byte) {
v := reflect.ValueOf(base)
if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() || v.Elem().Kind() != reflect.Struct {
return
}
v = unknownFieldsValue(v.Elem())
if !v.IsValid() {
return
}
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
// Verify that the raw field is valid.
for b0 := b; len(b0) > 0; {
fieldNum, _, n := wire.ConsumeField(b0)
if int32(fieldNum) != id {
panic(fmt.Sprintf("mismatching field number: got %d, want %d", fieldNum, id))
}
b0 = b0[n:]
}
fnum := protoreflect.FieldNumber(id)
v.SetBytes(append(removeRawFields(v.Bytes(), fnum), b...))
}
func removeRawFields(b []byte, fnum protoreflect.FieldNumber) []byte {
out := b[:0]
for len(b) > 0 {
got, _, n := wire.ConsumeField(b)
if got != fnum {
out = append(out, b[:n]...)
}
b = b[n:]
}
return out
}
// isExtensionField returns true iff the given field number is in an extension range.
func isExtensionField(pb Message, field int32) bool {
m, ok := pb.(interface{ ExtensionRangeArray() []ExtensionRange })
if ok {
for _, er := range m.ExtensionRangeArray() {
if er.Start <= field && field <= er.End {
return true
}
}
}
return false
}
// checkExtensionTypeAndRanges checks that the given extension is valid for pb.
func checkExtensionTypeAndRanges(pb Message, extension *ExtensionDesc) error {
// Check the extended type.
if extension.ExtendedType != nil {
if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
}
}
// Check the range.
if !isExtensionField(pb, extension.Field) {
return errors.New("proto: bad extension number; not in declared ranges")
}
return nil
}
// extPropKey is sufficient to uniquely identify an extension.
type extPropKey struct {
base reflect.Type
field int32
}
var extProp = struct {
sync.RWMutex
m map[extPropKey]*Properties
}{
m: make(map[extPropKey]*Properties),
}
func extensionProperties(pb Message, ed *ExtensionDesc) *Properties {
key := extPropKey{base: reflect.TypeOf(pb), field: ed.Field}
extProp.RLock()
if prop, ok := extProp.m[key]; ok {
extProp.RUnlock()
return prop
}
extProp.RUnlock()
extProp.Lock()
defer extProp.Unlock()
// Check again.
if prop, ok := extProp.m[key]; ok {
return prop
}
prop := new(Properties)
prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
extProp.m[key] = prop
return prop
}
// HasExtension returns whether the given extension is present in pb.
func HasExtension(pb Message, extension *ExtensionDesc) bool {
// TODO: Check types, field numbers, etc.?
epb, err := extendable(pb)
if err != nil || epb == nil {
// HasExtension reports whether the extension field is present in m
// either as an explicitly populated field or as an unknown field.
func HasExtension(m Message, xt *ExtensionDesc) (has bool) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return false
}
if epb.Has(protoreflect.FieldNumber(extension.Field)) {
return true
// Check whether any populated known field matches the field number.
xtd := xt.TypeDescriptor()
if isValidExtension(mr.Descriptor(), xtd) {
has = mr.Has(xtd)
} else {
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
has = int32(fd.Number()) == xt.Field
return !has
})
}
// Check whether this field exists in raw form.
unrecognized := unknownFieldsValue(reflect.ValueOf(pb).Elem())
fnum := protoreflect.FieldNumber(extension.Field)
for b := unrecognized.Bytes(); len(b) > 0; {
got, _, n := wire.ConsumeField(b)
if got == fnum {
return true
}
// Check whether any unknown field matches the field number.
for b := mr.GetUnknown(); !has && len(b) > 0; {
num, _, n := wire.ConsumeField(b)
has = int32(num) == xt.Field
b = b[n:]
}
return false
return has
}
// ClearExtension removes the given extension from pb.
func ClearExtension(pb Message, extension *ExtensionDesc) {
epb, err := extendable(pb)
if err != nil {
// ClearExtension removes the the exntesion field from m
// either as an explicitly populated field or as an unknown field.
func ClearExtension(m Message, xt *ExtensionDesc) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return
}
// TODO: Check types, field numbers, etc.?
epb.Clear(protoreflect.FieldNumber(extension.Field))
xtd := xt.TypeDescriptor()
if isValidExtension(mr.Descriptor(), xtd) {
mr.Clear(xtd)
} else {
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
if int32(fd.Number()) == xt.Field {
mr.Clear(fd)
return false
}
return true
})
}
clearUnknown(mr, fieldNum(xt.Field))
}
// ClearAllExtensions clears all extensions from m.
// This includes populated fields and unknown fields in the extension range.
func ClearAllExtensions(m Message) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return
}
mr.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
if fd.IsExtension() {
mr.Clear(fd)
}
return true
})
clearUnknown(mr, mr.Descriptor().ExtensionRanges())
}
// GetExtension retrieves a proto2 extended field from pb.
@ -234,276 +115,240 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
// If the field is not present, then the default value is returned (if one is specified),
// otherwise ErrMissingExtension is reported.
//
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
// then GetExtension returns the raw encoded bytes of the field extension.
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
// If the descriptor is type incomplete (i.e., ExtensionDesc.ExtensionType is nil),
// then GetExtension returns the raw encoded bytes for the extension field.
func GetExtension(m Message, xt *ExtensionDesc) (interface{}, error) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
return nil, errNotExtendable
}
// can only check type if this is a complete descriptor
if err := checkExtensionTypeAndRanges(pb, extension); err != nil {
return nil, err
}
unrecognized := unknownFieldsValue(reflect.ValueOf(pb).Elem())
var out []byte
fnum := protoreflect.FieldNumber(extension.Field)
for b := unrecognized.Bytes(); len(b) > 0; {
got, _, n := wire.ConsumeField(b)
if got == fnum {
out = append(out, b[:n]...)
// Retrieve the unknown fields for this extension field.
var bo protoreflect.RawFields
for bi := mr.GetUnknown(); len(bi) > 0; {
num, _, n := wire.ConsumeField(bi)
if int32(num) == xt.Field {
bo = append(bo, bi[:n]...)
}
b = b[n:]
bi = bi[n:]
}
if !epb.Has(protoreflect.FieldNumber(extension.Field)) && len(out) == 0 {
// defaultExtensionValue returns the default value or
// ErrMissingExtension if there is no default.
return defaultExtensionValue(pb, extension)
// For type incomplete descriptors, only retrieve the unknown fields.
if xt.ExtensionType == nil {
return []byte(bo), nil
}
e := epb.Get(protoreflect.FieldNumber(extension.Field))
if e.HasValue() {
// Already decoded. Check the descriptor, though.
if protoimpl.X.ExtensionDescFromType(e.GetType()) != extension {
// This shouldn't happen. If it does, it means that
// GetExtension was called twice with two different
// descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict")
}
return extensionAsLegacyType(e.GetValue()), nil
// If the extension field only exists as unknown fields, unmarshal it.
// This is rarely done since proto.Unmarshal eagerly unmarshals extensions.
xtd := xt.TypeDescriptor()
if !isValidExtension(mr.Descriptor(), xtd) {
return nil, fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
}
// Descriptor without type information.
if extension.ExtensionType == nil {
return out, nil
}
// TODO: Remove this logic for automatically unmarshaling the unknown fields.
v, err := decodeExtension(out, extension)
if err != nil {
return nil, err
}
// Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return.
e.SetType(extension)
e.SetEagerValue(extensionAsStorageType(v))
unrecognized.SetBytes(removeRawFields(unrecognized.Bytes(), fnum))
epb.Set(protoreflect.FieldNumber(extension.Field), e)
return extensionAsLegacyType(e.GetValue()), nil
}
// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue(pb Message, extension *ExtensionDesc) (interface{}, error) {
if extension.ExtensionType == nil {
// incomplete descriptor, so no default
return nil, ErrMissingExtension
}
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(pb, extension)
sf, _, err := fieldDefault(t, props)
if err != nil {
return nil, err
}
if sf == nil || sf.value == nil {
// There is no default value.
return nil, ErrMissingExtension
}
if t.Kind() != reflect.Ptr {
// We do not need to return a Ptr, we can directly return sf.value.
return sf.value, nil
}
// We need to return an interface{} that is a pointer to sf.value.
value := reflect.New(t).Elem()
value.Set(reflect.New(value.Type().Elem()))
if sf.kind == reflect.Int32 {
// We may have an int32 or an enum, but the underlying data is int32.
// Since we can't set an int32 into a non int32 reflect.Value directly
// set it as a int32.
value.Elem().SetInt(int64(sf.value.(int32)))
} else {
value.Elem().Set(reflect.ValueOf(sf.value))
}
return value.Interface(), nil
}
// decodeExtension decodes an extension encoded in b.
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
t := reflect.TypeOf(extension.ExtensionType)
unmarshal := typeUnmarshaler(t, extension.Tag)
// t is a pointer to a struct, pointer to basic type or a slice.
// Allocate space to store the pointer/slice.
value := reflect.New(t).Elem()
var err error
for {
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
wire := int(x) & 7
b, err = unmarshal(b, valToPointer(value.Addr()), wire)
if err != nil {
if !mr.Has(xtd) && len(bo) > 0 {
m2 := mr.New()
if err := (proto.UnmarshalOptions{
Resolver: extensionResolver{xt},
}.Unmarshal(bo, m2.Interface())); err != nil {
return nil, err
}
if len(b) == 0 {
break
}
}
return value.Interface(), nil
}
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
// The returned slice has the same length as es; missing extensions will appear as nil elements.
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
_, err = extendable(pb)
if err != nil {
return nil, err
}
extensions = make([]interface{}, len(es))
for i, e := range es {
extensions[i], err = GetExtension(pb, e)
if err == ErrMissingExtension {
err = nil
}
if err != nil {
return
}
}
return
}
// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
registeredExtensions := RegisteredExtensions(pb)
if epb == nil {
return nil, nil
}
extensions := make([]*ExtensionDesc, 0, epb.Len())
epb.Range(func(extid protoreflect.FieldNumber, e Extension) bool {
desc := protoimpl.X.ExtensionDescFromType(e.GetType())
if desc == nil {
desc = registeredExtensions[int32(extid)]
if desc == nil {
desc = &ExtensionDesc{Field: int32(extid)}
}
}
extensions = append(extensions, desc)
return true
})
unrecognized := unknownFieldsValue(reflect.ValueOf(pb).Elem())
if b := unrecognized.Bytes(); len(b) > 0 {
fieldNums := make(map[int32]bool)
for len(b) > 0 {
fnum, _, n := wire.ConsumeField(b)
if isExtensionField(pb, int32(fnum)) {
fieldNums[int32(fnum)] = true
}
b = b[n:]
}
for id := range fieldNums {
desc := registeredExtensions[id]
if desc == nil {
desc = &ExtensionDesc{Field: id}
}
extensions = append(extensions, desc)
if m2.Has(xtd) {
mr.Set(xtd, m2.Get(xtd))
clearUnknown(mr, fieldNum(xt.Field))
}
}
return extensions, nil
}
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
epb, err := extendable(pb)
if err != nil {
return err
}
if err := checkExtensionTypeAndRanges(pb, extension); err != nil {
return err
}
typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) {
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension
// from an ErrNil due to a missing field. Extensions are
// always optional, so the encoder would just swallow the error
// and drop all the extensions from the encoded message.
if reflect.ValueOf(value).IsNil() {
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
// Check whether the message has the extension field set or a default.
var pv protoreflect.Value
switch {
case mr.Has(xtd):
pv = mr.Get(xtd)
case xtd.HasDefault():
pv = xtd.Default()
default:
return nil, ErrMissingExtension
}
var x Extension
x.SetType(extension)
x.SetEagerValue(extensionAsStorageType(value))
epb.Set(protoreflect.FieldNumber(extension.Field), x)
return nil
}
// ClearAllExtensions clears all extensions from pb.
func ClearAllExtensions(pb Message) {
epb, err := extendable(pb)
if err != nil {
return
}
epb.Range(func(k protoreflect.FieldNumber, _ Extension) bool {
epb.Clear(k)
return true
})
}
// extensionAsLegacyType converts an value in the storage type as the API type.
// See Extension.Value.
func extensionAsLegacyType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
// Represent primitive types as a pointer to the value.
v := xt.InterfaceOf(pv)
rv := reflect.ValueOf(v)
if isScalarKind(rv.Kind()) {
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
}
return v
return v, nil
}
// extensionAsStorageType converts an value in the API type as the storage type.
// See Extension.Value.
func extensionAsStorageType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Ptr:
// Represent non-slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
// extensionResolver is a custom extension resolver that stores a single
// extension type that takes precedence over the global registry.
type extensionResolver struct{ xt protoreflect.ExtensionType }
func (r extensionResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
if xtd := r.xt.TypeDescriptor(); xtd.FullName() == field {
return r.xt, nil
}
return protoregistry.GlobalTypes.FindExtensionByName(field)
}
func (r extensionResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
if xtd := r.xt.TypeDescriptor(); xtd.ContainingMessage().FullName() == message && xtd.Number() == field {
return r.xt, nil
}
return protoregistry.GlobalTypes.FindExtensionByNumber(message, field)
}
// GetExtensions returns a list of the extensions values present in m,
// corresponding with the provided list of extension descriptors, xts.
// If an extension is missing in m, the corresponding value is nil.
func GetExtensions(m Message, xts []*ExtensionDesc) ([]interface{}, error) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return nil, errNotExtendable
}
vs := make([]interface{}, len(xts))
for i, xt := range xts {
v, err := GetExtension(m, xt)
if err != nil {
if err == ErrMissingExtension {
continue
}
return vs, err
}
vs[i] = v
}
return vs, nil
}
// SetExtension sets an extension field in m to the provided value.
func SetExtension(m Message, xt *ExtensionDesc, v interface{}) error {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
return errNotExtendable
}
rv := reflect.ValueOf(v)
if reflect.TypeOf(v) != reflect.TypeOf(xt.ExtensionType) {
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", v, xt.ExtensionType)
}
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
return fmt.Errorf("proto: SetExtension called with nil value of type %T", v)
}
if isScalarKind(rv.Elem().Kind()) {
v = rv.Elem().Interface()
}
}
return v
xtd := xt.TypeDescriptor()
if !isValidExtension(mr.Descriptor(), xtd) {
return fmt.Errorf("proto: bad extended type; %T does not extend %T", xt.ExtendedType, m)
}
mr.Set(xtd, xt.ValueOf(v))
clearUnknown(mr, fieldNum(xt.Field))
return nil
}
// SetRawExtension inserts b into the unknown fields of m.
//
// Deprecated: Use Message.ProtoReflect.SetUnknown instead.
func SetRawExtension(m Message, fnum int32, b []byte) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return
}
// Verify that the raw field is valid.
for b0 := b; len(b0) > 0; {
num, _, n := wire.ConsumeField(b0)
if int32(num) != fnum {
panic(fmt.Sprintf("mismatching field number: got %d, want %d", num, fnum))
}
b0 = b0[n:]
}
ClearExtension(m, &ExtensionDesc{Field: fnum})
mr.SetUnknown(append(mr.GetUnknown(), b...))
}
// ExtensionDescs returns a list of extension descriptors found in m,
// containing descriptors for both populated extension fields in m and
// also unknown fields of m that are in the extension range.
// For the later case, an type incomplete descriptor is provided where only
// the ExtensionDesc.Field field is populated.
// The order of the extension descriptors is undefined.
func ExtensionDescs(m Message) ([]*ExtensionDesc, error) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() || mr.Descriptor().ExtensionRanges().Len() == 0 {
return nil, errNotExtendable
}
// Collect a set of known extension descriptors.
extDescs := make(map[protoreflect.FieldNumber]*ExtensionDesc)
mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.IsExtension() {
xts := fd.(protoreflect.ExtensionTypeDescriptor)
extDescs[fd.Number()] = protoimpl.X.ExtensionDescFromType(xts.Type())
}
return true
})
// Collect a set of unknown extension descriptors.
extRanges := mr.Descriptor().ExtensionRanges()
for b := mr.GetUnknown(); len(b) > 0; {
num, _, n := wire.ConsumeField(b)
if extRanges.Has(num) && extDescs[num] == nil {
extDescs[num] = nil
}
b = b[n:]
}
// Transpose the set of descriptors into a list.
var xts []*ExtensionDesc
for num, xt := range extDescs {
if xt == nil {
xt = &ExtensionDesc{Field: int32(num)}
}
xts = append(xts, xt)
}
return xts, nil
}
// isValidExtension reports whether xtd is a valid extension descriptor for md.
func isValidExtension(md protoreflect.MessageDescriptor, xtd protoreflect.ExtensionTypeDescriptor) bool {
return xtd.ContainingMessage() == md && md.ExtensionRanges().Has(xtd.Number())
}
// isScalarKind reports whether k is a protobuf scalar kind (except bytes).
// This function exists for historical reasons since the representation of
// scalars differs between v1 and v2, where v1 uses *T and v2 uses T.
func isScalarKind(k reflect.Kind) bool {
switch k {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
return true
default:
return false
}
}
// clearUnknown removes unknown fields from m where remover.Has reports true.
func clearUnknown(m protoreflect.Message, remover interface {
Has(protoreflect.FieldNumber) bool
}) {
var bo protoreflect.RawFields
for bi := m.GetUnknown(); len(bi) > 0; {
num, _, n := wire.ConsumeField(bi)
if !remover.Has(num) {
bo = append(bo, bi[:n]...)
}
bi = bi[n:]
}
if bi := m.GetUnknown(); len(bi) != len(bo) {
m.SetUnknown(bo)
}
}
type fieldNum protoreflect.FieldNumber
func (n1 fieldNum) Has(n2 protoreflect.FieldNumber) bool {
return protoreflect.FieldNumber(n1) == n2
}

Просмотреть файл

@ -14,18 +14,19 @@ import (
"testing"
"github.com/golang/protobuf/proto"
pb "github.com/golang/protobuf/proto/test_proto"
pb2 "github.com/golang/protobuf/internal/testprotos/proto2_proto"
)
func TestGetExtensionsWithMissingExtensions(t *testing.T) {
msg := &pb.MyMessage{}
ext1 := &pb.Ext{}
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
msg := &pb2.MyMessage{}
ext1 := &pb2.Ext{}
if err := proto.SetExtension(msg, pb2.E_Ext_More, ext1); err != nil {
t.Fatalf("Could not set ext1: %s", err)
}
exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{
pb.E_Ext_More,
pb.E_Ext_Text,
pb2.E_Ext_More,
pb2.E_Ext_Text,
})
if err != nil {
t.Fatalf("GetExtensions() failed: %s", err)
@ -39,9 +40,9 @@ func TestGetExtensionsWithMissingExtensions(t *testing.T) {
}
func TestGetExtensionForIncompleteDesc(t *testing.T) {
msg := &pb.MyMessage{Count: proto.Int32(0)}
msg := &pb2.MyMessage{Count: proto.Int32(0)}
extdesc1 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtendedType: (*pb2.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 123456789,
Name: "a.b",
@ -52,7 +53,7 @@ func TestGetExtensionForIncompleteDesc(t *testing.T) {
t.Fatalf("Could not set ext1: %s", err)
}
extdesc2 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtendedType: (*pb2.MyMessage)(nil),
ExtensionType: ([]byte)(nil),
Field: 123456790,
Name: "a.c",
@ -63,13 +64,13 @@ func TestGetExtensionForIncompleteDesc(t *testing.T) {
t.Fatalf("Could not set ext2: %s", err)
}
extdesc3 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: (*pb.Ext)(nil),
ExtendedType: (*pb2.MyMessage)(nil),
ExtensionType: (*pb2.Ext)(nil),
Field: 123456791,
Name: "a.d",
Tag: "bytes,123456791,opt",
}
ext3 := &pb.Ext{Data: proto.String("foo")}
ext3 := &pb2.Ext{Data: proto.String("foo")}
if err := proto.SetExtension(msg, extdesc3, ext3); err != nil {
t.Fatalf("Could not set ext3: %s", err)
}
@ -128,18 +129,18 @@ func TestGetExtensionForIncompleteDesc(t *testing.T) {
}
func TestExtensionDescsWithUnregisteredExtensions(t *testing.T) {
msg := &pb.MyMessage{Count: proto.Int32(0)}
extdesc1 := pb.E_Ext_More
msg := &pb2.MyMessage{Count: proto.Int32(0)}
extdesc1 := pb2.E_Ext_More
if descs, err := proto.ExtensionDescs(msg); len(descs) != 0 || err != nil {
t.Errorf("proto.ExtensionDescs: got %d descs, error %v; want 0, nil", len(descs), err)
}
ext1 := &pb.Ext{}
ext1 := &pb2.Ext{}
if err := proto.SetExtension(msg, extdesc1, ext1); err != nil {
t.Fatalf("Could not set ext1: %s", err)
}
extdesc2 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtendedType: (*pb2.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 123456789,
Name: "a.b",
@ -180,20 +181,20 @@ func sortExtDescs(s []*proto.ExtensionDesc) {
}
func TestGetExtensionStability(t *testing.T) {
check := func(m *pb.MyMessage) bool {
ext1, err := proto.GetExtension(m, pb.E_Ext_More)
check := func(m *pb2.MyMessage) bool {
ext1, err := proto.GetExtension(m, pb2.E_Ext_More)
if err != nil {
t.Fatalf("GetExtension() failed: %s", err)
}
ext2, err := proto.GetExtension(m, pb.E_Ext_More)
ext2, err := proto.GetExtension(m, pb2.E_Ext_More)
if err != nil {
t.Fatalf("GetExtension() failed: %s", err)
}
return ext1 == ext2
}
msg := &pb.MyMessage{Count: proto.Int32(4)}
ext0 := &pb.Ext{}
if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil {
msg := &pb2.MyMessage{Count: proto.Int32(4)}
ext0 := &pb2.Ext{}
if err := proto.SetExtension(msg, pb2.E_Ext_More, ext0); err != nil {
t.Fatalf("Could not set ext1: %s", ext0)
}
if !check(msg) {
@ -203,7 +204,7 @@ func TestGetExtensionStability(t *testing.T) {
if err != nil {
t.Fatalf("Marshal() failed: %s", err)
}
msg1 := &pb.MyMessage{}
msg1 := &pb2.MyMessage{}
err = proto.Unmarshal(bb, msg1)
if err != nil {
t.Fatalf("Unmarshal() failed: %s", err)
@ -224,7 +225,7 @@ func TestGetExtensionDefaults(t *testing.T) {
var setBool2 = false
var setString = "Goodnight string"
var setBytes = []byte("Goodnight bytes")
var setEnum = pb.DefaultsMessage_TWO
var setEnum = pb2.DefaultsMessage_TWO
type testcase struct {
ext *proto.ExtensionDesc // Extension we are testing.
@ -232,43 +233,43 @@ func TestGetExtensionDefaults(t *testing.T) {
def interface{} // Expected value of extension after ClearExtension().
}
tests := []testcase{
{pb.E_NoDefaultDouble, setFloat64, nil},
{pb.E_NoDefaultFloat, setFloat32, nil},
{pb.E_NoDefaultInt32, setInt32, nil},
{pb.E_NoDefaultInt64, setInt64, nil},
{pb.E_NoDefaultUint32, setUint32, nil},
{pb.E_NoDefaultUint64, setUint64, nil},
{pb.E_NoDefaultSint32, setInt32, nil},
{pb.E_NoDefaultSint64, setInt64, nil},
{pb.E_NoDefaultFixed32, setUint32, nil},
{pb.E_NoDefaultFixed64, setUint64, nil},
{pb.E_NoDefaultSfixed32, setInt32, nil},
{pb.E_NoDefaultSfixed64, setInt64, nil},
{pb.E_NoDefaultBool, setBool, nil},
{pb.E_NoDefaultBool, setBool2, nil},
{pb.E_NoDefaultString, setString, nil},
{pb.E_NoDefaultBytes, setBytes, nil},
{pb.E_NoDefaultEnum, setEnum, nil},
{pb.E_DefaultDouble, setFloat64, float64(3.1415)},
{pb.E_DefaultFloat, setFloat32, float32(3.14)},
{pb.E_DefaultInt32, setInt32, int32(42)},
{pb.E_DefaultInt64, setInt64, int64(43)},
{pb.E_DefaultUint32, setUint32, uint32(44)},
{pb.E_DefaultUint64, setUint64, uint64(45)},
{pb.E_DefaultSint32, setInt32, int32(46)},
{pb.E_DefaultSint64, setInt64, int64(47)},
{pb.E_DefaultFixed32, setUint32, uint32(48)},
{pb.E_DefaultFixed64, setUint64, uint64(49)},
{pb.E_DefaultSfixed32, setInt32, int32(50)},
{pb.E_DefaultSfixed64, setInt64, int64(51)},
{pb.E_DefaultBool, setBool, true},
{pb.E_DefaultBool, setBool2, true},
{pb.E_DefaultString, setString, "Hello, string,def=foo"},
{pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
{pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE},
{pb2.E_NoDefaultDouble, setFloat64, nil},
{pb2.E_NoDefaultFloat, setFloat32, nil},
{pb2.E_NoDefaultInt32, setInt32, nil},
{pb2.E_NoDefaultInt64, setInt64, nil},
{pb2.E_NoDefaultUint32, setUint32, nil},
{pb2.E_NoDefaultUint64, setUint64, nil},
{pb2.E_NoDefaultSint32, setInt32, nil},
{pb2.E_NoDefaultSint64, setInt64, nil},
{pb2.E_NoDefaultFixed32, setUint32, nil},
{pb2.E_NoDefaultFixed64, setUint64, nil},
{pb2.E_NoDefaultSfixed32, setInt32, nil},
{pb2.E_NoDefaultSfixed64, setInt64, nil},
{pb2.E_NoDefaultBool, setBool, nil},
{pb2.E_NoDefaultBool, setBool2, nil},
{pb2.E_NoDefaultString, setString, nil},
{pb2.E_NoDefaultBytes, setBytes, nil},
{pb2.E_NoDefaultEnum, setEnum, nil},
{pb2.E_DefaultDouble, setFloat64, float64(3.1415)},
{pb2.E_DefaultFloat, setFloat32, float32(3.14)},
{pb2.E_DefaultInt32, setInt32, int32(42)},
{pb2.E_DefaultInt64, setInt64, int64(43)},
{pb2.E_DefaultUint32, setUint32, uint32(44)},
{pb2.E_DefaultUint64, setUint64, uint64(45)},
{pb2.E_DefaultSint32, setInt32, int32(46)},
{pb2.E_DefaultSint64, setInt64, int64(47)},
{pb2.E_DefaultFixed32, setUint32, uint32(48)},
{pb2.E_DefaultFixed64, setUint64, uint64(49)},
{pb2.E_DefaultSfixed32, setInt32, int32(50)},
{pb2.E_DefaultSfixed64, setInt64, int64(51)},
{pb2.E_DefaultBool, setBool, true},
{pb2.E_DefaultBool, setBool2, true},
{pb2.E_DefaultString, setString, "Hello, string,def=foo"},
{pb2.E_DefaultBytes, setBytes, []byte("Hello, bytes")},
{pb2.E_DefaultEnum, setEnum, pb2.DefaultsMessage_ONE},
}
checkVal := func(t *testing.T, name string, test testcase, msg *pb.DefaultsMessage, valWant interface{}) {
checkVal := func(t *testing.T, name string, test testcase, msg *pb2.DefaultsMessage, valWant interface{}) {
t.Run(name, func(t *testing.T) {
val, err := proto.GetExtension(msg, test.ext)
if err != nil {
@ -328,7 +329,7 @@ func TestGetExtensionDefaults(t *testing.T) {
}
for _, test := range tests {
msg := &pb.DefaultsMessage{}
msg := &pb2.DefaultsMessage{}
name := test.ext.Name
// Check the initial value.
@ -349,7 +350,7 @@ func TestGetExtensionDefaults(t *testing.T) {
func TestNilMessage(t *testing.T) {
name := "nil interface"
if got, err := proto.GetExtension(nil, pb.E_Ext_More); err == nil {
if got, err := proto.GetExtension(nil, pb2.E_Ext_More); err == nil {
t.Errorf("%s: got %T %v, expected to fail", name, got, got)
} else if !strings.Contains(err.Error(), "extendable") {
t.Errorf("%s: got error %v, expected not-extendable error", name, err)
@ -358,8 +359,8 @@ func TestNilMessage(t *testing.T) {
// Regression tests: all functions of the Extension API
// used to panic when passed (*M)(nil), where M is a concrete message
// type. Now they handle this gracefully as a no-op or reported error.
var nilMsg *pb.MyMessage
desc := pb.E_Ext_More
var nilMsg *pb2.MyMessage
desc := pb2.E_Ext_More
isNotExtendable := func(err error) bool {
return strings.Contains(fmt.Sprint(err), "not an extendable")
@ -386,58 +387,52 @@ func TestNilMessage(t *testing.T) {
}
func TestExtensionsRoundTrip(t *testing.T) {
msg := &pb.MyMessage{}
ext1 := &pb.Ext{
msg := &pb2.MyMessage{}
ext1 := &pb2.Ext{
Data: proto.String("hi"),
}
ext2 := &pb.Ext{
ext2 := &pb2.Ext{
Data: proto.String("there"),
}
exists := proto.HasExtension(msg, pb.E_Ext_More)
exists := proto.HasExtension(msg, pb2.E_Ext_More)
if exists {
t.Error("Extension More present unexpectedly")
}
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
if err := proto.SetExtension(msg, pb2.E_Ext_More, ext1); err != nil {
t.Error(err)
}
if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil {
if err := proto.SetExtension(msg, pb2.E_Ext_More, ext2); err != nil {
t.Error(err)
}
e, err := proto.GetExtension(msg, pb.E_Ext_More)
e, err := proto.GetExtension(msg, pb2.E_Ext_More)
if err != nil {
t.Error(err)
}
x, ok := e.(*pb.Ext)
x, ok := e.(*pb2.Ext)
if !ok {
t.Errorf("e has type %T, expected test_proto.Ext", e)
} else if *x.Data != "there" {
t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x)
}
proto.ClearExtension(msg, pb.E_Ext_More)
if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension {
proto.ClearExtension(msg, pb2.E_Ext_More)
if _, err = proto.GetExtension(msg, pb2.E_Ext_More); err != proto.ErrMissingExtension {
t.Errorf("got %v, expected ErrMissingExtension", e)
}
if _, err := proto.GetExtension(msg, pb.E_X215); err == nil {
t.Error("expected bad extension error, got nil")
}
if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil {
t.Error("expected extension err")
}
if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil {
if err := proto.SetExtension(msg, pb2.E_Ext_More, 12); err == nil {
t.Error("expected some sort of type mismatch error, got nil")
}
}
func TestNilExtension(t *testing.T) {
msg := &pb.MyMessage{
msg := &pb2.MyMessage{
Count: proto.Int32(1),
}
if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil {
if err := proto.SetExtension(msg, pb2.E_Ext_Text, proto.String("hello")); err != nil {
t.Fatal(err)
}
if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil {
if err := proto.SetExtension(msg, pb2.E_Ext_More, (*pb2.Ext)(nil)); err == nil {
t.Error("expected SetExtension to fail due to a nil extension")
} else if want := fmt.Sprintf("proto: SetExtension called with nil value of type %T", new(pb.Ext)); err.Error() != want {
} else if want := fmt.Sprintf("proto: SetExtension called with nil value of type %T", new(pb2.Ext)); err.Error() != want {
t.Errorf("expected error %v, got %v", want, err)
}
// Note: if the behavior of Marshal is ever changed to ignore nil extensions, update
@ -448,25 +443,25 @@ func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
// Add a repeated extension to the result.
tests := []struct {
name string
ext []*pb.ComplexExtension
ext []*pb2.ComplexExtension
}{
{
"two fields",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{First: proto.Int32(7)},
{Second: proto.Int32(11)},
},
},
{
"repeated field",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{Third: []int32{1000}},
{Third: []int32{2000}},
},
},
{
"two fields and repeated field",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{Third: []int32{1000}},
{First: proto.Int32(9)},
{Second: proto.Int32(21)},
@ -476,8 +471,8 @@ func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
}
for _, test := range tests {
// Marshal message with a repeated extension.
msg1 := new(pb.OtherMessage)
err := proto.SetExtension(msg1, pb.E_RComplex, test.ext)
msg1 := new(pb2.OtherMessage)
err := proto.SetExtension(msg1, pb2.E_RComplex, test.ext)
if err != nil {
t.Fatalf("[%s] Error setting extension: %v", test.name, err)
}
@ -487,16 +482,16 @@ func TestMarshalUnmarshalRepeatedExtension(t *testing.T) {
}
// Unmarshal and read the merged proto.
msg2 := new(pb.OtherMessage)
msg2 := new(pb2.OtherMessage)
err = proto.Unmarshal(b, msg2)
if err != nil {
t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
}
e, err := proto.GetExtension(msg2, pb.E_RComplex)
e, err := proto.GetExtension(msg2, pb2.E_RComplex)
if err != nil {
t.Fatalf("[%s] Error getting extension: %v", test.name, err)
}
ext := e.([]*pb.ComplexExtension)
ext := e.([]*pb2.ComplexExtension)
if ext == nil {
t.Fatalf("[%s] Invalid extension", test.name)
}
@ -517,25 +512,25 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
// this way. Here, we verify that we merge the extensions together.
tests := []struct {
name string
ext []*pb.ComplexExtension
ext []*pb2.ComplexExtension
}{
{
"two fields",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{First: proto.Int32(7)},
{Second: proto.Int32(11)},
},
},
{
"repeated field",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{Third: []int32{1000}},
{Third: []int32{2000}},
},
},
{
"two fields and repeated field",
[]*pb.ComplexExtension{
[]*pb2.ComplexExtension{
{Third: []int32{1000}},
{First: proto.Int32(9)},
{Second: proto.Int32(21)},
@ -545,7 +540,7 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
}
for _, test := range tests {
var buf bytes.Buffer
var want pb.ComplexExtension
var want pb2.ComplexExtension
// Generate a serialized representation of a repeated extension
// by catenating bytes together.
@ -554,8 +549,8 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
proto.Merge(&want, e)
// serialize the message
msg := new(pb.OtherMessage)
err := proto.SetExtension(msg, pb.E_Complex, e)
msg := new(pb2.OtherMessage)
err := proto.SetExtension(msg, pb2.E_Complex, e)
if err != nil {
t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err)
}
@ -567,16 +562,16 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
}
// Unmarshal and read the merged proto.
msg2 := new(pb.OtherMessage)
msg2 := new(pb2.OtherMessage)
err := proto.Unmarshal(buf.Bytes(), msg2)
if err != nil {
t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err)
}
e, err := proto.GetExtension(msg2, pb.E_Complex)
e, err := proto.GetExtension(msg2, pb2.E_Complex)
if err != nil {
t.Fatalf("[%s] Error getting extension: %v", test.name, err)
}
ext := e.(*pb.ComplexExtension)
ext := e.(*pb2.ComplexExtension)
if ext == nil {
t.Fatalf("[%s] Invalid extension", test.name)
}
@ -589,13 +584,13 @@ func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) {
func TestClearAllExtensions(t *testing.T) {
// unregistered extension
desc := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtendedType: (*pb2.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 101010100,
Name: "emptyextension",
Tag: "varint,0,opt",
}
m := &pb.MyMessage{}
m := &pb2.MyMessage{}
if proto.HasExtension(m, desc) {
t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m))
}
@ -612,9 +607,9 @@ func TestClearAllExtensions(t *testing.T) {
}
func TestMarshalRace(t *testing.T) {
ext := &pb.Ext{}
m := &pb.MyMessage{Count: proto.Int32(4)}
if err := proto.SetExtension(m, pb.E_Ext_More, ext); err != nil {
ext := &pb2.Ext{}
m := &pb2.MyMessage{Count: proto.Int32(4)}
if err := proto.SetExtension(m, pb2.E_Ext_More, ext); err != nil {
t.Fatalf("proto.SetExtension(m, desc, true): got error %q, want nil", err)
}

Просмотреть файл

@ -1,152 +0,0 @@
// 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.
// +build use_golang_protobuf_v1
package proto
import (
"io"
"reflect"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/apipb"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/fieldmaskpb"
"google.golang.org/protobuf/types/known/sourcecontextpb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/typepb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
var (
// Hooks for lib.go.
setDefaultsAlt func(Message)
// Hooks for discard.go.
discardUnknownAlt func(Message)
// Hooks for registry.go.
registerEnumAlt func(string, map[int32]string, map[string]int32)
enumValueMapAlt func(string) map[string]int32
registerTypeAlt func(Message, string)
registerMapTypeAlt func(interface{}, string)
messageNameAlt func(Message) string
messageTypeAlt func(string) reflect.Type
registerFileAlt func(string, []byte)
fileDescriptorAlt func(string) []byte
registerExtensionAlt func(*ExtensionDesc)
registeredExtensionsAlt func(Message) map[int32]*ExtensionDesc
// Hooks for text.go
marshalTextAlt func(io.Writer, Message) error
marshalTextStringAlt func(Message) string
compactTextAlt func(io.Writer, Message) error
compactTextStringAlt func(Message) string
// Hooks for text_parser.go
unmarshalTextAlt func(string, Message) error
)
// Hooks for lib.go.
type RequiredNotSetError = requiredNotSetError
// Hooks for text.go
type TextMarshaler = textMarshaler
// The v2 descriptor no longer registers with v1.
// If we're only relying on the v1 registry, we need to manually register the
// types in descriptor.
func init() {
// TODO: This should be eventually deleted once the v1 repository is fully
// switched over to wrap the v2 repository.
rawDesc, _ := (*descriptorpb.DescriptorProto)(nil).Descriptor()
RegisterFile("google/protobuf/descriptor.proto", rawDesc)
RegisterEnum("google.protobuf.FieldDescriptorProto_Type", descriptorpb.FieldDescriptorProto_Type_name, descriptorpb.FieldDescriptorProto_Type_value)
RegisterEnum("google.protobuf.FieldDescriptorProto_Label", descriptorpb.FieldDescriptorProto_Label_name, descriptorpb.FieldDescriptorProto_Label_value)
RegisterEnum("google.protobuf.FileOptions_OptimizeMode", descriptorpb.FileOptions_OptimizeMode_name, descriptorpb.FileOptions_OptimizeMode_value)
RegisterEnum("google.protobuf.FieldOptions_CType", descriptorpb.FieldOptions_CType_name, descriptorpb.FieldOptions_CType_value)
RegisterEnum("google.protobuf.FieldOptions_JSType", descriptorpb.FieldOptions_JSType_name, descriptorpb.FieldOptions_JSType_value)
RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", descriptorpb.MethodOptions_IdempotencyLevel_name, descriptorpb.MethodOptions_IdempotencyLevel_value)
RegisterType((*descriptorpb.FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet")
RegisterType((*descriptorpb.FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto")
RegisterType((*descriptorpb.DescriptorProto)(nil), "google.protobuf.DescriptorProto")
RegisterType((*descriptorpb.ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions")
RegisterType((*descriptorpb.FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto")
RegisterType((*descriptorpb.OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto")
RegisterType((*descriptorpb.EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto")
RegisterType((*descriptorpb.EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto")
RegisterType((*descriptorpb.ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto")
RegisterType((*descriptorpb.MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto")
RegisterType((*descriptorpb.FileOptions)(nil), "google.protobuf.FileOptions")
RegisterType((*descriptorpb.MessageOptions)(nil), "google.protobuf.MessageOptions")
RegisterType((*descriptorpb.FieldOptions)(nil), "google.protobuf.FieldOptions")
RegisterType((*descriptorpb.OneofOptions)(nil), "google.protobuf.OneofOptions")
RegisterType((*descriptorpb.EnumOptions)(nil), "google.protobuf.EnumOptions")
RegisterType((*descriptorpb.EnumValueOptions)(nil), "google.protobuf.EnumValueOptions")
RegisterType((*descriptorpb.ServiceOptions)(nil), "google.protobuf.ServiceOptions")
RegisterType((*descriptorpb.MethodOptions)(nil), "google.protobuf.MethodOptions")
RegisterType((*descriptorpb.UninterpretedOption)(nil), "google.protobuf.UninterpretedOption")
RegisterType((*descriptorpb.SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo")
RegisterType((*descriptorpb.GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo")
RegisterType((*descriptorpb.DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange")
RegisterType((*descriptorpb.DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange")
RegisterType((*descriptorpb.EnumDescriptorProto_EnumReservedRange)(nil), "google.protobuf.EnumDescriptorProto.EnumReservedRange")
RegisterType((*descriptorpb.UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart")
RegisterType((*descriptorpb.SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location")
RegisterType((*descriptorpb.GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation")
// any.proto
RegisterType((*anypb.Any)(nil), "google.protobuf.Any")
// api.proto
RegisterType((*apipb.Api)(nil), "google.protobuf.Api")
RegisterType((*apipb.Method)(nil), "google.protobuf.Method")
RegisterType((*apipb.Mixin)(nil), "google.protobuf.Mixin")
// duration.proto
RegisterType((*durationpb.Duration)(nil), "google.protobuf.Duration")
// empty.proto
RegisterType((*emptypb.Empty)(nil), "google.protobuf.Empty")
// field_mask.proto
RegisterType((*fieldmaskpb.FieldMask)(nil), "google.protobuf.FieldMask")
// source_context.proto
RegisterType((*sourcecontextpb.SourceContext)(nil), "google.protobuf.SourceContext")
// struct.proto
RegisterEnum("google.protobuf.NullValue", structpb.NullValue_name, structpb.NullValue_value)
RegisterType((*structpb.Struct)(nil), "google.protobuf.Struct")
RegisterType((*structpb.Value)(nil), "google.protobuf.Value")
RegisterType((*structpb.ListValue)(nil), "google.protobuf.ListValue")
// timestamp.proto
RegisterType((*timestamppb.Timestamp)(nil), "google.protobuf.Timestamp")
// type.proto
RegisterEnum("google.protobuf.Syntax", typepb.Syntax_name, typepb.Syntax_value)
RegisterEnum("google.protobuf.Field_Kind", typepb.Field_Kind_name, typepb.Field_Kind_value)
RegisterEnum("google.protobuf.Field_Cardinality", typepb.Field_Cardinality_name, typepb.Field_Cardinality_value)
RegisterType((*typepb.Type)(nil), "google.protobuf.Type")
RegisterType((*typepb.Field)(nil), "google.protobuf.Field")
RegisterType((*typepb.Enum)(nil), "google.protobuf.Enum")
RegisterType((*typepb.EnumValue)(nil), "google.protobuf.EnumValue")
RegisterType((*typepb.Option)(nil), "google.protobuf.Option")
// wrapper.proto
RegisterType((*wrapperspb.DoubleValue)(nil), "google.protobuf.DoubleValue")
RegisterType((*wrapperspb.FloatValue)(nil), "google.protobuf.FloatValue")
RegisterType((*wrapperspb.Int64Value)(nil), "google.protobuf.Int64Value")
RegisterType((*wrapperspb.UInt64Value)(nil), "google.protobuf.UInt64Value")
RegisterType((*wrapperspb.Int32Value)(nil), "google.protobuf.Int32Value")
RegisterType((*wrapperspb.UInt32Value)(nil), "google.protobuf.UInt32Value")
RegisterType((*wrapperspb.BoolValue)(nil), "google.protobuf.BoolValue")
RegisterType((*wrapperspb.StringValue)(nil), "google.protobuf.StringValue")
RegisterType((*wrapperspb.BytesValue)(nil), "google.protobuf.BytesValue")
}

Просмотреть файл

@ -1,46 +0,0 @@
// 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.
// +build !use_golang_protobuf_v1
package proto
import (
"github.com/golang/protobuf/internal/proto"
)
var (
// Hooks for lib.go.
setDefaultsAlt = proto.SetDefaults
// Hooks for discard.go.
discardUnknownAlt = proto.DiscardUnknown
// Hooks for registry.go.
registerEnumAlt = proto.RegisterEnum
enumValueMapAlt = proto.EnumValueMap
registerTypeAlt = proto.RegisterType
registerMapTypeAlt = proto.RegisterMapType
messageNameAlt = proto.MessageName
messageTypeAlt = proto.MessageType
registerFileAlt = proto.RegisterFile
fileDescriptorAlt = proto.FileDescriptor
registerExtensionAlt = proto.RegisterExtension
registeredExtensionsAlt = proto.RegisteredExtensions
// Hooks for text.go
marshalTextAlt = proto.MarshalText
marshalTextStringAlt = proto.MarshalTextString
compactTextAlt = proto.CompactText
compactTextStringAlt = proto.CompactTextString
// Hooks for text_parser.go
unmarshalTextAlt = proto.UnmarshalText
)
// Hooks for lib.go.
type RequiredNotSetError = proto.RequiredNotSetError
// Hooks for text.go
type TextMarshaler = proto.TextMarshaler

Просмотреть файл

@ -1,692 +0,0 @@
// Copyright 2010 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.
// Package proto marshals and unmarshals protocol buffer messages as the
// wire-format and text-format. For more information, see:
// https://developers.google.com/protocol-buffers/docs/gotutorial
package proto
import (
"fmt"
"log"
"reflect"
"sort"
"strconv"
"sync"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/runtime/protoiface"
"google.golang.org/protobuf/runtime/protoimpl"
)
// requiredNotSetError is an error type returned by either Marshal or Unmarshal.
// Marshal reports this when a required field is not initialized.
// Unmarshal reports this when a required field is missing from the wire data.
type requiredNotSetError struct{ field string }
func (e *requiredNotSetError) Error() string {
if e.field == "" {
return fmt.Sprintf("proto: required field not set")
}
return fmt.Sprintf("proto: required field %q not set", e.field)
}
func (e *requiredNotSetError) RequiredNotSet() bool {
return true
}
type invalidUTF8Error struct{ field string }
func (e *invalidUTF8Error) Error() string {
if e.field == "" {
return "proto: invalid UTF-8 detected"
}
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
}
func (e *invalidUTF8Error) InvalidUTF8() bool {
return true
}
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
// This error should not be exposed to the external API as such errors should
// be recreated with the field information.
var errInvalidUTF8 = &invalidUTF8Error{}
// isNonFatal reports whether the error is either a RequiredNotSet error
// or a InvalidUTF8 error.
func isNonFatal(err error) bool {
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
return true
}
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
return true
}
return false
}
type nonFatal struct{ E error }
// Merge merges err into nf and reports whether it was successful.
// Otherwise it returns false for any fatal non-nil errors.
func (nf *nonFatal) Merge(err error) (ok bool) {
if err == nil {
return true // not an error
}
if !isNonFatal(err) {
return false // fatal error
}
if nf.E == nil {
nf.E = err // store first instance of non-fatal error
}
return true
}
// Message is implemented by generated protocol buffer messages.
type Message = protoiface.MessageV1
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
var marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// oneofWrappers returns a list of oneof wrappers for t,
// which must be a named struct type.
func oneofWrappers(t reflect.Type) []interface{} {
var oos []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oos = m.XXX_OneofFuncs()
case oneofWrappersIface:
oos = m.XXX_OneofWrappers()
case protoV2.Message:
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
oos = m.ProtoMessageInfo().OneofWrappers
}
}
return oos
}
// unknownFieldsValue retrieves the value for unknown fields from v,
// which must be a name struct type.
func unknownFieldsValue(v reflect.Value) reflect.Value {
if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
return vf
}
if vf := fieldByName(v, "unknownFields"); vf.IsValid() {
return vf
}
return reflect.Value{}
}
// extensionFieldsValue retrieves the value for extension fields from v,
// which must be a name struct type.
func extensionFieldsValue(v reflect.Value) reflect.Value {
if vf := v.FieldByName("XXX_InternalExtensions"); vf.IsValid() {
return vf
}
if vf := v.FieldByName("XXX_extensions"); vf.IsValid() {
return vf
}
if vf := fieldByName(v, "extensionFields"); vf.IsValid() {
return vf
}
return reflect.Value{}
}
// exporterFunc retrieves the field exporter function for t,
// which must be a named struct type.
func exporterFunc(t reflect.Type) func(interface{}, int) interface{} {
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoV2.Message); ok {
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
return m.ProtoMessageInfo().Exporter
}
}
return nil
}
// isMessageSet determines whether t is a MessageSet message,
// where t must be a named struct type.
func isMessageSet(t reflect.Type) bool {
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoV2.Message); ok {
md := m.ProtoReflect().Descriptor()
xmd, ok := md.(interface{ IsMessageSet() bool })
return ok && xmd.IsMessageSet()
}
return false
}
// A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to
// reduce memory usage. It is not necessary to use a Buffer;
// the global functions Marshal and Unmarshal create a
// temporary Buffer and are fine for most applications.
type Buffer struct {
buf []byte // encode/decode byte stream
index int // read point
deterministic bool
}
// NewBuffer allocates a new Buffer and initializes its internal data to
// the contents of the argument slice.
func NewBuffer(e []byte) *Buffer {
return &Buffer{buf: e}
}
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
func (p *Buffer) Reset() {
p.buf = p.buf[0:0] // for reading/writing
p.index = 0 // for reading
}
// SetBuf replaces the internal buffer with the slice,
// ready for unmarshaling the contents of the slice.
func (p *Buffer) SetBuf(s []byte) {
p.buf = s
p.index = 0
}
// Bytes returns the contents of the Buffer.
func (p *Buffer) Bytes() []byte { return p.buf }
// SetDeterministic sets whether to use deterministic serialization.
//
// Deterministic serialization guarantees that for a given binary, equal
// messages will always be serialized to the same bytes. This implies:
//
// - Repeated serialization of a message will return the same bytes.
// - Different processes of the same binary (which may be executing on
// different machines) will serialize equal messages to the same bytes.
//
// Note that the deterministic serialization is NOT canonical across
// languages. It is not guaranteed to remain stable over time. It is unstable
// across different builds with schema changes due to unknown fields.
// Users who need canonical serialization (e.g., persistent storage in a
// canonical form, fingerprinting, etc.) should define their own
// canonicalization specification and implement their own serializer rather
// than relying on this API.
//
// If deterministic serialization is requested, map entries will be sorted
// by keys in lexographical order. This is an implementation detail and
// subject to change.
func (p *Buffer) SetDeterministic(deterministic bool) {
p.deterministic = deterministic
}
// DebugPrint dumps the encoded data in b in a debugging format with a header
// including the string s. Used in testing but made available for general debugging.
func (p *Buffer) DebugPrint(s string, b []byte) {
var u uint64
obuf := p.buf
index := p.index
p.buf = b
p.index = 0
depth := 0
fmt.Printf("\n--- %s ---\n", s)
out:
for {
for i := 0; i < depth; i++ {
fmt.Print(" ")
}
index := p.index
if index == len(p.buf) {
break
}
op, err := p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: fetching op err %v\n", index, err)
break out
}
tag := op >> 3
wire := op & 7
switch wire {
default:
fmt.Printf("%3d: t=%3d unknown wire=%d\n",
index, tag, wire)
break out
case WireBytes:
var r []byte
r, err = p.DecodeRawBytes(false)
if err != nil {
break out
}
fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
if len(r) <= 6 {
for i := 0; i < len(r); i++ {
fmt.Printf(" %.2x", r[i])
}
} else {
for i := 0; i < 3; i++ {
fmt.Printf(" %.2x", r[i])
}
fmt.Printf(" ..")
for i := len(r) - 3; i < len(r); i++ {
fmt.Printf(" %.2x", r[i])
}
}
fmt.Printf("\n")
case WireFixed32:
u, err = p.DecodeFixed32()
if err != nil {
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
case WireFixed64:
u, err = p.DecodeFixed64()
if err != nil {
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
case WireVarint:
u, err = p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
case WireStartGroup:
fmt.Printf("%3d: t=%3d start\n", index, tag)
depth++
case WireEndGroup:
depth--
fmt.Printf("%3d: t=%3d end\n", index, tag)
}
}
if depth != 0 {
fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
}
fmt.Printf("\n")
p.buf = obuf
p.index = index
}
// SetDefaults sets unset protocol buffer fields to their default values.
// It only modifies fields that are both unset and have defined defaults.
// It recursively sets default values in any non-nil sub-messages.
func SetDefaults(pb Message) {
if setDefaultsAlt != nil {
setDefaultsAlt(pb) // populated by hooks_enabled.go
return
}
setDefaults(reflect.ValueOf(pb), true, false)
}
// v is a pointer to a struct.
func setDefaults(v reflect.Value, recur, zeros bool) {
v = v.Elem()
defaultMu.RLock()
dm, ok := defaults[v.Type()]
defaultMu.RUnlock()
if !ok {
dm = buildDefaultMessage(v.Type())
defaultMu.Lock()
defaults[v.Type()] = dm
defaultMu.Unlock()
}
for _, sf := range dm.scalars {
f := v.Field(sf.index)
if !f.IsNil() {
// field already set
continue
}
dv := sf.value
if dv == nil && !zeros {
// no explicit default, and don't want to set zeros
continue
}
fptr := f.Addr().Interface() // **T
// TODO: Consider batching the allocations we do here.
switch sf.kind {
case reflect.Bool:
b := new(bool)
if dv != nil {
*b = dv.(bool)
}
*(fptr.(**bool)) = b
case reflect.Float32:
f := new(float32)
if dv != nil {
*f = dv.(float32)
}
*(fptr.(**float32)) = f
case reflect.Float64:
f := new(float64)
if dv != nil {
*f = dv.(float64)
}
*(fptr.(**float64)) = f
case reflect.Int32:
// might be an enum
if ft := f.Type(); ft != int32PtrType {
// enum
f.Set(reflect.New(ft.Elem()))
if dv != nil {
f.Elem().SetInt(int64(dv.(int32)))
}
} else {
// int32 field
i := new(int32)
if dv != nil {
*i = dv.(int32)
}
*(fptr.(**int32)) = i
}
case reflect.Int64:
i := new(int64)
if dv != nil {
*i = dv.(int64)
}
*(fptr.(**int64)) = i
case reflect.String:
s := new(string)
if dv != nil {
*s = dv.(string)
}
*(fptr.(**string)) = s
case reflect.Uint8:
// exceptional case: []byte
var b []byte
if dv != nil {
db := dv.([]byte)
b = make([]byte, len(db))
copy(b, db)
} else {
b = []byte{}
}
*(fptr.(*[]byte)) = b
case reflect.Uint32:
u := new(uint32)
if dv != nil {
*u = dv.(uint32)
}
*(fptr.(**uint32)) = u
case reflect.Uint64:
u := new(uint64)
if dv != nil {
*u = dv.(uint64)
}
*(fptr.(**uint64)) = u
default:
log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
}
}
for _, ni := range dm.nested {
f := v.Field(ni)
// f is *T or []*T or map[T]*T
switch f.Kind() {
case reflect.Ptr:
if f.IsNil() {
continue
}
setDefaults(f, recur, zeros)
case reflect.Slice:
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
}
case reflect.Map:
for _, k := range f.MapKeys() {
e := f.MapIndex(k)
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
}
}
}
}
var (
// defaults maps a protocol buffer struct type to a slice of the fields,
// with its scalar fields set to their proto-declared non-zero default values.
defaultMu sync.RWMutex
defaults = make(map[reflect.Type]defaultMessage)
int32PtrType = reflect.TypeOf((*int32)(nil))
)
// defaultMessage represents information about the default values of a message.
type defaultMessage struct {
scalars []scalarField
nested []int // struct field index of nested messages
}
type scalarField struct {
index int // struct field index
kind reflect.Kind // element type (the T in *T or []T)
value interface{} // the proto-declared default value, or nil
}
// t is a struct type.
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
sprop := GetProperties(t)
for fi, prop := range sprop.Prop {
if prop.Tag <= 0 {
// XXX_unrecognized
continue
}
ft := t.Field(fi).Type
sf, nested, err := fieldDefault(ft, prop)
switch {
case err != nil:
log.Print(err)
case nested:
dm.nested = append(dm.nested, fi)
case sf != nil:
sf.index = fi
dm.scalars = append(dm.scalars, *sf)
}
}
return dm
}
// fieldDefault returns the scalarField for field type ft.
// sf will be nil if the field can not have a default.
// nestedMessage will be true if this is a nested message.
// Note that sf.index is not set on return.
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
var canHaveDefault bool
switch ft.Kind() {
case reflect.Ptr:
if ft.Elem().Kind() == reflect.Struct {
nestedMessage = true
} else {
canHaveDefault = true // proto2 scalar field
}
case reflect.Slice:
switch ft.Elem().Kind() {
case reflect.Ptr:
nestedMessage = true // repeated message
case reflect.Uint8:
canHaveDefault = true // bytes field
}
case reflect.Map:
if ft.Elem().Kind() == reflect.Ptr {
nestedMessage = true // map with message values
}
}
if !canHaveDefault {
if nestedMessage {
return nil, true, nil
}
return nil, false, nil
}
// We now know that ft is a pointer or slice.
sf = &scalarField{kind: ft.Elem().Kind()}
// scalar fields without defaults
if !prop.HasDefault {
return sf, false, nil
}
// a scalar field: either *T or []byte
switch ft.Elem().Kind() {
case reflect.Bool:
x, err := strconv.ParseBool(prop.Default)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Float32:
x, err := strconv.ParseFloat(prop.Default, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
}
sf.value = float32(x)
case reflect.Float64:
x, err := strconv.ParseFloat(prop.Default, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Int32:
x, err := strconv.ParseInt(prop.Default, 10, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
}
sf.value = int32(x)
case reflect.Int64:
x, err := strconv.ParseInt(prop.Default, 10, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.String:
sf.value = prop.Default
case reflect.Uint8:
// []byte (not *uint8)
sf.value = []byte(prop.Default)
case reflect.Uint32:
x, err := strconv.ParseUint(prop.Default, 10, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
}
sf.value = uint32(x)
case reflect.Uint64:
x, err := strconv.ParseUint(prop.Default, 10, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
}
sf.value = x
default:
return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
}
return sf, false, nil
}
// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
func mapKeys(vs []reflect.Value) sort.Interface {
s := mapKeySorter{vs: vs}
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
if len(vs) == 0 {
return s
}
switch vs[0].Kind() {
case reflect.Int32, reflect.Int64:
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
case reflect.Bool:
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
case reflect.String:
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
default:
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
}
return s
}
type mapKeySorter struct {
vs []reflect.Value
less func(a, b reflect.Value) bool
}
func (s mapKeySorter) Len() int { return len(s.vs) }
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
func (s mapKeySorter) Less(i, j int) bool {
return s.less(s.vs[i], s.vs[j])
}
// isProto3Zero reports whether v is a zero proto3 value.
func isProto3Zero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return !v.Bool()
case reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint32, reflect.Uint64:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.String:
return v.String() == ""
}
return false
}
const (
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion3 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion1 = true
)
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.
// This type is not subject to any compatibility guarantee.
type InternalMessageInfo struct {
marshal *marshalInfo
unmarshal *unmarshalInfo
merge *mergeInfo
discard *discardInfo
}

Просмотреть файл

@ -1,74 +0,0 @@
// Copyright 2016 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.
package proto_test
import (
"fmt"
"reflect"
"testing"
"github.com/golang/protobuf/proto"
ppb "github.com/golang/protobuf/proto/proto3_proto"
)
func TestMap(t *testing.T) {
var b []byte
fmt.Sscanf("a2010c0a044b657931120456616c31a201130a044b657932120556616c3261120456616c32a201240a044b6579330d05000000120556616c33621a0556616c3361120456616c331505000000a20100a201260a044b657934130a07536f6d6555524c1209536f6d655469746c651a08536e69707065743114", "%x", &b)
var m ppb.Message
if err := proto.Unmarshal(b, &m); err != nil {
t.Fatalf("proto.Unmarshal error: %v", err)
}
got := m.StringMap
want := map[string]string{
"": "",
"Key1": "Val1",
"Key2": "Val2",
"Key3": "Val3",
"Key4": "",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("maps differ:\ngot %#v\nwant %#v", got, want)
}
}
func marshalled() []byte {
m := &ppb.IntMaps{}
for i := 0; i < 1000; i++ {
m.Maps = append(m.Maps, &ppb.IntMap{
Rtt: map[int32]int32{1: 2},
})
}
b, err := proto.Marshal(m)
if err != nil {
panic(fmt.Sprintf("Can't marshal %+v: %v", m, err))
}
return b
}
func BenchmarkConcurrentMapUnmarshal(b *testing.B) {
in := marshalled()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var out ppb.IntMaps
if err := proto.Unmarshal(in, &out); err != nil {
b.Errorf("Can't unmarshal ppb.IntMaps: %v", err)
}
}
})
}
func BenchmarkSequentialMapUnmarshal(b *testing.B) {
in := marshalled()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var out ppb.IntMaps
if err := proto.Unmarshal(in, &out); err != nil {
b.Errorf("Can't unmarshal ppb.IntMaps: %v", err)
}
}
}

Просмотреть файл

@ -1,140 +0,0 @@
// Copyright 2010 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.
package proto
/*
* Support for message sets.
*/
import (
"errors"
"reflect"
"google.golang.org/protobuf/reflect/protoreflect"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
// A message type ID is required for storing a protocol buffer in a message set.
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
// The first two types (_MessageSet_Item and messageSet)
// model what the protocol compiler produces for the following protocol message:
// message MessageSet {
// repeated group Item = 1 {
// required int32 type_id = 2;
// required string message = 3;
// };
// }
// That is the MessageSet wire format. We can't use a proto to generate these
// because that would introduce a circular dependency between it and this package.
type _MessageSet_Item struct {
TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
Message []byte `protobuf:"bytes,3,req,name=message"`
}
type messageSet struct {
Item []*_MessageSet_Item `protobuf:"group,1,rep"`
XXX_unrecognized []byte
// TODO: caching?
}
// Make sure messageSet is a Message.
var _ Message = (*messageSet)(nil)
// messageTypeIder is an interface satisfied by a protocol buffer type
// that may be stored in a MessageSet.
type messageTypeIder interface {
MessageTypeId() int32
}
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
mti, ok := pb.(messageTypeIder)
if !ok {
return nil
}
id := mti.MessageTypeId()
for _, item := range ms.Item {
if *item.TypeId == id {
return item
}
}
return nil
}
func (ms *messageSet) Has(pb Message) bool {
return ms.find(pb) != nil
}
func (ms *messageSet) Unmarshal(pb Message) error {
if item := ms.find(pb); item != nil {
return Unmarshal(item.Message, pb)
}
if _, ok := pb.(messageTypeIder); !ok {
return errNoMessageTypeID
}
return nil // TODO: return error instead?
}
func (ms *messageSet) Marshal(pb Message) error {
msg, err := Marshal(pb)
if err != nil {
return err
}
if item := ms.find(pb); item != nil {
// reuse existing item
item.Message = msg
return nil
}
mti, ok := pb.(messageTypeIder)
if !ok {
return errNoMessageTypeID
}
mtid := mti.MessageTypeId()
ms.Item = append(ms.Item, &_MessageSet_Item{
TypeId: &mtid,
Message: msg,
})
return nil
}
func (ms *messageSet) Reset() { *ms = messageSet{} }
func (ms *messageSet) String() string { return CompactTextString(ms) }
func (*messageSet) ProtoMessage() {}
// Support for the message_set_wire_format message option.
func skipVarint(buf []byte) []byte {
i := 0
for ; buf[i]&0x80 != 0; i++ {
}
return buf[i+1:]
}
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func unmarshalMessageSet(buf []byte, mi Message, exts interface{}) error {
ms := new(messageSet)
if err := Unmarshal(buf, ms); err != nil {
return err
}
unrecognized := unknownFieldsValue(reflect.ValueOf(mi).Elem()).Addr().Interface().(*[]byte)
for _, item := range ms.Item {
id := protoreflect.FieldNumber(*item.TypeId)
msg := item.Message
// Restore wire type and field number varint, plus length varint.
b := EncodeVarint(uint64(id)<<3 | WireBytes)
b = append(b, EncodeVarint(uint64(len(msg)))...)
b = append(b, msg...)
*unrecognized = append(*unrecognized, b...)
}
return unmarshalExtensions(mi, unrecognized)
}

Просмотреть файл

@ -1,67 +0,0 @@
// Copyright 2014 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.
package proto_test
import (
"bytes"
"fmt"
"testing"
"github.com/golang/protobuf/proto"
. "github.com/golang/protobuf/proto/test_proto"
)
func TestUnmarshalMessageSetWithDuplicate(t *testing.T) {
/*
Message{
Tag{1, StartGroup},
Message{
Tag{2, Varint}, Uvarint(12345),
Tag{3, Bytes}, Bytes("hoo"),
},
Tag{1, EndGroup},
Tag{1, StartGroup},
Message{
Tag{2, Varint}, Uvarint(12345),
Tag{3, Bytes}, Bytes("hah"),
},
Tag{1, EndGroup},
}
*/
var in []byte
fmt.Sscanf("0b10b9601a03686f6f0c0b10b9601a036861680c", "%x", &in)
/*
Message{
Tag{1, StartGroup},
Message{
Tag{2, Varint}, Uvarint(12345),
Tag{3, Bytes}, Bytes("hoo"),
},
Tag{1, EndGroup},
Tag{1, StartGroup},
Message{
Tag{2, Varint}, Uvarint(12345),
Tag{3, Bytes}, Bytes("hah"),
},
Tag{1, EndGroup},
}
*/
var want []byte
fmt.Sscanf("0b10b9601a03686f6f0c0b10b9601a036861680c", "%x", &want)
var m MyMessageSet
if err := proto.Unmarshal(in, &m); err != nil {
t.Fatalf("unexpected Unmarshal error: %v", err)
}
got, err := proto.Marshal(&m)
if err != nil {
t.Fatalf("unexpected Marshal error: %v", err)
}
if !bytes.Equal(got, want) {
t.Errorf("output mismatch:\ngot %x\nwant %x", got, want)
}
}

Просмотреть файл

@ -1,371 +0,0 @@
// Copyright 2012 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.
// +build purego
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
// be used on App Engine.
package proto
import (
"reflect"
"sync"
"unicode"
"unicode/utf8"
)
const unsafeAllowed = false
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by the sequence of field indices
// passed to reflect's FieldByIndex.
type field struct {
index int
export exporter
}
type exporter = func(interface{}, int) interface{}
// toField returns a field equivalent to the given reflect field.
func toField(f *reflect.StructField, x exporter) field {
if len(f.Index) != 1 {
panic("embedded structs are not supported")
}
if f.PkgPath == "" {
return field{index: f.Index[0]} // field is already exported
}
if x == nil {
panic("exporter must be provided for unexported field: " + f.Name)
}
return field{index: f.Index[0], export: x}
}
// invalidField is an invalid field identifier.
var invalidField = field{index: -1}
// zeroField is a noop when calling pointer.offset.
var zeroField = field{index: 0}
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool { return f.index >= 0 }
// The pointer type is for the table-driven decoder.
// The implementation here uses a reflect.Value of pointer type to
// create a generic pointer. In pointer_unsafe.go we use unsafe
// instead of reflect to implement the same (but faster) interface.
type pointer struct {
v reflect.Value
}
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
return pointer{v: reflect.ValueOf(*i)}
}
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
v := reflect.ValueOf(*i)
u := reflect.New(v.Type())
u.Elem().Set(v)
if deref {
u = u.Elem()
}
return pointer{v: u}
}
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{v: v}
}
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
if f.export != nil {
if v := reflect.ValueOf(f.export(p.v.Interface(), f.index)); v.IsValid() {
return pointer{v: v}
}
}
return pointer{v: p.v.Elem().Field(f.index).Addr()}
}
func (p pointer) isNil() bool {
return p.v.IsNil()
}
// grow updates the slice s in place to make it one element longer.
// s must be addressable.
// Returns the (addressable) new element.
func grow(s reflect.Value) reflect.Value {
n, m := s.Len(), s.Cap()
if n < m {
s.SetLen(n + 1)
} else {
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
}
return s.Index(n)
}
func (p pointer) toInt64() *int64 {
return p.v.Interface().(*int64)
}
func (p pointer) toInt64Ptr() **int64 {
return p.v.Interface().(**int64)
}
func (p pointer) toInt64Slice() *[]int64 {
return p.v.Interface().(*[]int64)
}
var int32ptr = reflect.TypeOf((*int32)(nil))
func (p pointer) toInt32() *int32 {
return p.v.Convert(int32ptr).Interface().(*int32)
}
// The toInt32Ptr/Slice methods don't work because of enums.
// Instead, we must use set/get methods for the int32ptr/slice case.
/*
func (p pointer) toInt32Ptr() **int32 {
return p.v.Interface().(**int32)
}
func (p pointer) toInt32Slice() *[]int32 {
return p.v.Interface().(*[]int32)
}
*/
func (p pointer) getInt32Ptr() *int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().(*int32)
}
// an enum
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
}
func (p pointer) setInt32Ptr(v int32) {
// Allocate value in a *int32. Possibly convert that to a *enum.
// Then assign it to a **int32 or **enum.
// Note: we can convert *int32 to *enum, but we can't convert
// **int32 to **enum!
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
}
// getInt32Slice copies []int32 from p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getInt32Slice() []int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().([]int32)
}
// an enum
// Allocate a []int32, then assign []enum's values into it.
// Note: we can't convert []enum to []int32.
slice := p.v.Elem()
s := make([]int32, slice.Len())
for i := 0; i < slice.Len(); i++ {
s[i] = int32(slice.Index(i).Int())
}
return s
}
// setInt32Slice copies []int32 into p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setInt32Slice(v []int32) {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
p.v.Elem().Set(reflect.ValueOf(v))
return
}
// an enum
// Allocate a []enum, then assign []int32's values into it.
// Note: we can't convert []enum to []int32.
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
for i, x := range v {
slice.Index(i).SetInt(int64(x))
}
p.v.Elem().Set(slice)
}
func (p pointer) appendInt32Slice(v int32) {
grow(p.v.Elem()).SetInt(int64(v))
}
func (p pointer) toUint64() *uint64 {
return p.v.Interface().(*uint64)
}
func (p pointer) toUint64Ptr() **uint64 {
return p.v.Interface().(**uint64)
}
func (p pointer) toUint64Slice() *[]uint64 {
return p.v.Interface().(*[]uint64)
}
func (p pointer) toUint32() *uint32 {
return p.v.Interface().(*uint32)
}
func (p pointer) toUint32Ptr() **uint32 {
return p.v.Interface().(**uint32)
}
func (p pointer) toUint32Slice() *[]uint32 {
return p.v.Interface().(*[]uint32)
}
func (p pointer) toBool() *bool {
return p.v.Interface().(*bool)
}
func (p pointer) toBoolPtr() **bool {
return p.v.Interface().(**bool)
}
func (p pointer) toBoolSlice() *[]bool {
return p.v.Interface().(*[]bool)
}
func (p pointer) toFloat64() *float64 {
return p.v.Interface().(*float64)
}
func (p pointer) toFloat64Ptr() **float64 {
return p.v.Interface().(**float64)
}
func (p pointer) toFloat64Slice() *[]float64 {
return p.v.Interface().(*[]float64)
}
func (p pointer) toFloat32() *float32 {
return p.v.Interface().(*float32)
}
func (p pointer) toFloat32Ptr() **float32 {
return p.v.Interface().(**float32)
}
func (p pointer) toFloat32Slice() *[]float32 {
return p.v.Interface().(*[]float32)
}
func (p pointer) toString() *string {
return p.v.Interface().(*string)
}
func (p pointer) toStringPtr() **string {
return p.v.Interface().(**string)
}
func (p pointer) toStringSlice() *[]string {
return p.v.Interface().(*[]string)
}
func (p pointer) toBytes() *[]byte {
return p.v.Interface().(*[]byte)
}
func (p pointer) toBytesSlice() *[][]byte {
return p.v.Interface().(*[][]byte)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return p.v.Interface().(*XXX_InternalExtensions)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return p.v.Interface().(*map[int32]Extension)
}
func (p pointer) getPointer() pointer {
return pointer{v: p.v.Elem()}
}
func (p pointer) setPointer(q pointer) {
p.v.Elem().Set(q.v)
}
func (p pointer) appendPointer(q pointer) {
grow(p.v.Elem()).Set(q.v)
}
// getPointerSlice copies []*T from p as a new []pointer.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getPointerSlice() []pointer {
if p.v.IsNil() {
return nil
}
n := p.v.Elem().Len()
s := make([]pointer, n)
for i := 0; i < n; i++ {
s[i] = pointer{v: p.v.Elem().Index(i)}
}
return s
}
// setPointerSlice copies []pointer into p as a new []*T.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setPointerSlice(v []pointer) {
if v == nil {
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
return
}
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
for _, p := range v {
s = reflect.Append(s, p.v)
}
p.v.Elem().Set(s)
}
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
if p.v.Elem().IsNil() {
return pointer{v: p.v.Elem()}
}
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
}
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
// TODO: check that p.v.Type().Elem() == t?
return p.v
}
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
var atomicLock sync.Mutex
// fieldByName is equivalent to reflect.Value.FieldByName, but is able to
// descend into unexported fields for prop
func fieldByName(v reflect.Value, s string) reflect.Value {
if r, _ := utf8.DecodeRuneInString(s); unicode.IsUpper(r) {
return v.FieldByName(s)
}
t := v.Type()
if x := exporterFunc(t); x != nil {
sf, ok := t.FieldByName(s)
if ok {
vi := x(v.Addr().Interface(), sf.Index[0])
return reflect.ValueOf(vi).Elem()
}
}
return v.FieldByName(s)
}

Просмотреть файл

@ -1,303 +0,0 @@
// Copyright 2012 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.
// +build !purego
// This file contains the implementation of the proto field accesses using package unsafe.
package proto
import (
"reflect"
"sync/atomic"
"unicode"
"unicode/utf8"
"unsafe"
)
const unsafeAllowed = true
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by its byte offset from the start of the struct.
type field uintptr
type exporter = func(interface{}, int) interface{}
// toField returns a field equivalent to the given reflect field.
func toField(f *reflect.StructField, x exporter) field {
return field(f.Offset)
}
// invalidField is an invalid field identifier.
const invalidField = ^field(0)
// zeroField is a noop when calling pointer.offset.
const zeroField = field(0)
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool {
return f != invalidField
}
// The pointer type below is for the new table-driven encoder/decoder.
// The implementation here uses unsafe.Pointer to create a generic pointer.
// In pointer_reflect.go we use reflect instead of unsafe to implement
// the same (but slower) interface.
type pointer struct {
p unsafe.Pointer
}
// size of pointer
var ptrSize = unsafe.Sizeof(uintptr(0))
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
// Super-tricky - read pointer out of data word of interface value.
// Saves ~25ns over the equivalent:
// return valToPointer(reflect.ValueOf(*i))
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
// Super-tricky - read or get the address of data word of interface value.
if isptr {
// The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address.
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
} else {
// The interface is not of pointer type. The data word is the pointer
// to the data.
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
if deref {
p.p = *(*unsafe.Pointer)(p.p)
}
return p
}
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{p: unsafe.Pointer(v.Pointer())}
}
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
// For safety, we should panic if !f.IsValid, however calling panic causes
// this to no longer be inlineable, which is a serious performance cost.
/*
if !f.IsValid() {
panic("invalid field")
}
*/
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
}
func (p pointer) isNil() bool {
return p.p == nil
}
func (p pointer) toInt64() *int64 {
return (*int64)(p.p)
}
func (p pointer) toInt64Ptr() **int64 {
return (**int64)(p.p)
}
func (p pointer) toInt64Slice() *[]int64 {
return (*[]int64)(p.p)
}
func (p pointer) toInt32() *int32 {
return (*int32)(p.p)
}
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
/*
func (p pointer) toInt32Ptr() **int32 {
return (**int32)(p.p)
}
func (p pointer) toInt32Slice() *[]int32 {
return (*[]int32)(p.p)
}
*/
func (p pointer) getInt32Ptr() *int32 {
return *(**int32)(p.p)
}
func (p pointer) setInt32Ptr(v int32) {
*(**int32)(p.p) = &v
}
// getInt32Slice loads a []int32 from p.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getInt32Slice() []int32 {
return *(*[]int32)(p.p)
}
// setInt32Slice stores a []int32 to p.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setInt32Slice(v []int32) {
*(*[]int32)(p.p) = v
}
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
func (p pointer) appendInt32Slice(v int32) {
s := (*[]int32)(p.p)
*s = append(*s, v)
}
func (p pointer) toUint64() *uint64 {
return (*uint64)(p.p)
}
func (p pointer) toUint64Ptr() **uint64 {
return (**uint64)(p.p)
}
func (p pointer) toUint64Slice() *[]uint64 {
return (*[]uint64)(p.p)
}
func (p pointer) toUint32() *uint32 {
return (*uint32)(p.p)
}
func (p pointer) toUint32Ptr() **uint32 {
return (**uint32)(p.p)
}
func (p pointer) toUint32Slice() *[]uint32 {
return (*[]uint32)(p.p)
}
func (p pointer) toBool() *bool {
return (*bool)(p.p)
}
func (p pointer) toBoolPtr() **bool {
return (**bool)(p.p)
}
func (p pointer) toBoolSlice() *[]bool {
return (*[]bool)(p.p)
}
func (p pointer) toFloat64() *float64 {
return (*float64)(p.p)
}
func (p pointer) toFloat64Ptr() **float64 {
return (**float64)(p.p)
}
func (p pointer) toFloat64Slice() *[]float64 {
return (*[]float64)(p.p)
}
func (p pointer) toFloat32() *float32 {
return (*float32)(p.p)
}
func (p pointer) toFloat32Ptr() **float32 {
return (**float32)(p.p)
}
func (p pointer) toFloat32Slice() *[]float32 {
return (*[]float32)(p.p)
}
func (p pointer) toString() *string {
return (*string)(p.p)
}
func (p pointer) toStringPtr() **string {
return (**string)(p.p)
}
func (p pointer) toStringSlice() *[]string {
return (*[]string)(p.p)
}
func (p pointer) toBytes() *[]byte {
return (*[]byte)(p.p)
}
func (p pointer) toBytesSlice() *[][]byte {
return (*[][]byte)(p.p)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return (*XXX_InternalExtensions)(p.p)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return (*map[int32]Extension)(p.p)
}
// getPointerSlice loads []*T from p as a []pointer.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getPointerSlice() []pointer {
// Super-tricky - p should point to a []*T where T is a
// message type. We load it as []pointer.
return *(*[]pointer)(p.p)
}
// setPointerSlice stores []pointer into p as a []*T.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setPointerSlice(v []pointer) {
// Super-tricky - p should point to a []*T where T is a
// message type. We store it as []pointer.
*(*[]pointer)(p.p) = v
}
// getPointer loads the pointer at p and returns it.
func (p pointer) getPointer() pointer {
return pointer{p: *(*unsafe.Pointer)(p.p)}
}
// setPointer stores the pointer q at p.
func (p pointer) setPointer(q pointer) {
*(*unsafe.Pointer)(p.p) = q.p
}
// append q to the slice pointed to by p.
func (p pointer) appendPointer(q pointer) {
s := (*[]unsafe.Pointer)(p.p)
*s = append(*s, q.p)
}
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
// Super-tricky - read pointer out of data word of interface value.
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
}
// asPointerTo returns a reflect.Value that is a pointer to an
// object of type t stored at p.
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
return reflect.NewAt(t, p.p)
}
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
// fieldByName is equivalent to reflect.Value.FieldByName, but is able to
// descend into unexported fields for prop
func fieldByName(v reflect.Value, s string) reflect.Value {
if r, _ := utf8.DecodeRuneInString(s); unicode.IsUpper(r) {
return v.FieldByName(s)
}
sf, ok := v.Type().FieldByName(s)
if !ok {
return reflect.Value{}
}
return reflect.NewAt(sf.Type, unsafe.Pointer(v.UnsafeAddr()+sf.Offset)).Elem()
}

Просмотреть файл

@ -2,68 +2,97 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build use_golang_protobuf_v1
package proto
import (
"fmt"
"reflect"
"strconv"
"strings"
"sync"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoimpl"
)
// Constants that identify the encoding of a value on the wire.
const (
WireVarint = 0
WireFixed32 = 5
WireFixed64 = 1
WireBytes = 2
WireStartGroup = 3
WireEndGroup = 4
)
// StructProperties represents properties for all the fields of a struct.
// StructProperties represents protocol buffer type information for a
// generated protobuf message in the open-struct API.
//
// Deprecated: Do not use.
type StructProperties struct {
Prop []*Properties // properties for each field
// Prop are the properties for each field.
//
// Fields belonging to a oneof are stored in OneofTypes instead, with a
// single Properties representing the parent oneof held here.
//
// The order of Prop matches the order of fields in the Go struct.
// Struct fields that are not related to protobufs have a "XXX_" prefix
// in the Properties.Name and must be ignored by the user.
Prop []*Properties
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the original name of a field.
// It is keyed by the protobuf field name.
OneofTypes map[string]*OneofProperties
}
// OneofProperties represents information about a specific field in a oneof.
type OneofProperties struct {
Type reflect.Type // pointer to generated struct type for this oneof field
Field int // struct field number of the containing oneof in the message
Prop *Properties
// Properties represents the type information for a protobuf message field.
//
// Deprecated: Do not use.
type Properties struct {
// Name is a placeholder name with little meaningful semantic value.
// If the name has an "XXX_" prefix, the entire Properties must be ignored.
Name string
// OrigName is the protobuf field name or oneof name.
OrigName string
// JSONName is the JSON name for the protobuf field.
JSONName string
// Enum is a placeholder name for enums.
// For historical reasons, this is neither the Go name for the enum,
// nor the protobuf name for the enum.
Enum string // Deprecated: Do not use.
// Weak contains the full name of the weakly referenced message.
Weak string
// Wire is a string representation of the wire type.
Wire string
// WireType is the protobuf wire type for the field.
WireType int
// Tag is the protobuf field number.
Tag int
// Required reports whether this is a required field.
Required bool
// Optional reports whether this is a optional field.
Optional bool
// Repeated reports whether this is a repeated field.
Repeated bool
// Packed reports whether this is a packed repeated field of scalars.
Packed bool
// Proto3 reports whether this field operates under the proto3 syntax.
Proto3 bool
// Oneof reports whether this field belongs within a oneof.
Oneof bool
// Default is the default value in string form.
Default string
// HasDefault reports whether the field has a default value.
HasDefault bool
// MapKeyProp is the properties for the key field for a map field.
MapKeyProp *Properties
// MapValProp is the properties for the value field for a map field.
MapValProp *Properties
}
func (sp *StructProperties) Len() int { return len(sp.Prop) }
func (sp *StructProperties) Less(i, j int) bool { return false }
func (sp *StructProperties) Swap(i, j int) { return }
// Properties represents the protocol-specific behavior of a single struct field.
type Properties struct {
Name string // name of the field, for error messages
OrigName string // original name before protocol compiler (always set)
JSONName string // name to use for JSON; determined by protoc
Wire string
WireType int
Tag int
Required bool
Optional bool
Repeated bool
Packed bool // relevant for repeated primitives only
Enum string // set for enum types only
Proto3 bool // whether this is known to be a proto3 field
Oneof bool // whether this is a oneof field
Default string // default value
HasDefault bool // whether an explicit default was provided
MapKeyProp *Properties // set for map types only
MapValProp *Properties // set for map types only
// OneofProperties represents the type information for a protobuf oneof.
//
// Deprecated: Do not use.
type OneofProperties struct {
// Type is a pointer to the generated wrapper type for the field value.
// This is nil for messages that are not in the open-struct API.
Type reflect.Type
// Field is the index into StructProperties.Prop for the containing oneof.
Field int
// Prop is the properties for the field.
Prop *Properties
}
// String formats the properties in the protobuf struct field tag style.
@ -86,15 +115,18 @@ func (p *Properties) String() string {
if p.JSONName != "" {
s += ",json=" + p.JSONName
}
if len(p.Enum) > 0 {
s += ",enum=" + p.Enum
}
if len(p.Weak) > 0 {
s += ",weak=" + p.Weak
}
if p.Proto3 {
s += ",proto3"
}
if p.Oneof {
s += ",oneof"
}
if len(p.Enum) > 0 {
s += ",enum=" + p.Enum
}
if p.HasDefault {
s += ",def=" + p.Default
}
@ -116,6 +148,8 @@ func (p *Properties) Parse(tag string) {
p.JSONName = s[len("json="):]
case strings.HasPrefix(s, "enum="):
p.Enum = s[len("enum="):]
case strings.HasPrefix(s, "weak="):
p.Weak = s[len("weak="):]
case strings.Trim(s, "0123456789") == "":
n, _ := strconv.ParseUint(s, 10, 32)
p.Tag = int(n)
@ -157,11 +191,9 @@ func (p *Properties) Parse(tag string) {
}
// Init populates the properties from a protocol buffer struct tag.
//
// Deprecated: Do not use.
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.init(typ, name, tag, f)
}
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.Name = name
p.OrigName = name
if tag == "" {
@ -171,16 +203,19 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
if typ != nil && typ.Kind() == reflect.Map {
p.MapKeyProp = new(Properties)
p.MapKeyProp.init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
p.MapKeyProp.Init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
p.MapValProp = new(Properties)
p.MapValProp.init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
p.MapValProp.Init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
}
}
var propertiesCache sync.Map // map[reflect.Type]*StructProperties
// GetProperties returns the list of properties for the type represented by t.
// t must represent a generated struct type of a protocol message.
// GetProperties returns the list of properties for the type represented by t,
// which must be a generated protocol buffer message in the open-struct API,
// where protobuf message fields are represented by exported Go struct fields.
//
// Deprecated: Use protobuf reflection instead.
func GetProperties(t reflect.Type) *StructProperties {
if p, ok := propertiesCache.Load(t); ok {
return p.(*StructProperties)
@ -191,27 +226,54 @@ func GetProperties(t reflect.Type) *StructProperties {
func newProperties(t reflect.Type) *StructProperties {
if t.Kind() != reflect.Struct {
panic("proto: type must have kind struct")
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
}
var hasOneof bool
prop := new(StructProperties)
// Construct a list of properties for each field in the struct.
for i := 0; i < t.NumField(); i++ {
p := new(Properties)
f := t.Field(i)
p.init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
tagField := f.Tag.Get("protobuf")
p.Init(f.Type, f.Name, tagField, &f)
if name := f.Tag.Get("protobuf_oneof"); name != "" {
p.OrigName = name
tagOneof := f.Tag.Get("protobuf_oneof")
if tagOneof != "" {
hasOneof = true
p.OrigName = tagOneof
}
// Rename unrelated struct fields with the "XXX_" prefix since so much
// user code simply checks for this to exclude special fields.
if tagField == "" && tagOneof == "" && !strings.HasPrefix(p.Name, "XXX_") {
p.Name = "XXX_" + p.Name
p.OrigName = "XXX_" + p.OrigName
} else if p.Weak != "" {
p.Name = p.OrigName // avoid possible "XXX_" prefix on weak field
}
prop.Prop = append(prop.Prop, p)
}
// Construct a mapping of oneof field names to properties.
if oneofImplementors := oneofWrappers(t); len(oneofImplementors) > 0 {
if hasOneof {
var oneofWrappers []interface{}
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3].Interface().([]interface{})
}
if fn, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
oneofWrappers = fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0].Interface().([]interface{})
}
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(protoreflect.ProtoMessage); ok {
if m, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *protoimpl.MessageInfo }); ok {
oneofWrappers = m.ProtoMessageInfo().OneofWrappers
}
}
prop.OneofTypes = make(map[string]*OneofProperties)
for _, wrapper := range oneofImplementors {
for _, wrapper := range oneofWrappers {
p := &OneofProperties{
Type: reflect.ValueOf(wrapper).Type(), // *T
Prop: new(Properties),
@ -222,15 +284,23 @@ func newProperties(t reflect.Type) *StructProperties {
// Determine the struct field that contains this oneof.
// Each wrapper is assignable to exactly one parent field.
for i := 0; i < t.NumField(); i++ {
var foundOneof bool
for i := 0; i < t.NumField() && !foundOneof; i++ {
if p.Type.AssignableTo(t.Field(i).Type) {
p.Field = i
break
foundOneof = true
}
}
if !foundOneof {
panic(fmt.Sprintf("%v is not a generated message in the open-struct API", t))
}
prop.OneofTypes[p.Prop.OrigName] = p
}
}
return prop
}
func (sp *StructProperties) Len() int { return len(sp.Prop) }
func (sp *StructProperties) Less(i, j int) bool { return false }
func (sp *StructProperties) Swap(i, j int) { return }

Просмотреть файл

@ -1,33 +0,0 @@
// Copyright 2010 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.
// +build !use_golang_protobuf_v1
package proto
import (
"reflect"
"github.com/golang/protobuf/internal/proto"
)
// Constants that identify the encoding of a value on the wire.
const (
WireVarint = 0
WireFixed64 = 1
WireBytes = 2
WireStartGroup = 3
WireEndGroup = 4
WireFixed32 = 5
)
type (
Properties = proto.Properties
StructProperties = proto.StructProperties
OneofProperties = proto.OneofProperties
)
func GetProperties(t reflect.Type) *StructProperties {
return proto.GetProperties(t)
}

140
proto/proto.go Normal file
Просмотреть файл

@ -0,0 +1,140 @@
// 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.
// Package proto provides functionality for handling protocol buffer messages.
// In particular, it provides marshaling and unmarshaling between a protobuf
// message and the binary wire format.
//
// See https://developers.google.com/protocol-buffers/docs/gotutorial for
// more information.
//
// Deprecated: Use the "google.golang.org/protobuf/proto" package instead.
package proto
import (
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/runtime/protoiface"
"google.golang.org/protobuf/runtime/protoimpl"
)
// Message is a protocol buffer message.
type Message = protoiface.MessageV1
// Marshaler is implemented by messages that can marshal themselves.
// This interface is used by the following functions: Size, Marshal,
// Buffer.Marshal, and Buffer.EncodeMessage.
//
// Deprecated: Do not implement.
type Marshaler interface {
// Marshal formats the encoded bytes of the message.
// It should be deterministic and emit valid protobuf wire data.
// The caller takes ownership of the returned buffer.
Marshal() ([]byte, error)
}
// Unmarshaler is implemented by messages that can unmarshal themselves.
// This interface is used by the following functions: Unmarshal, UnmarshalMerge,
// Buffer.Unmarshal, Buffer.DecodeMessage, and Buffer.DecodeGroup.
//
// Deprecated: Do not implement.
type Unmarshaler interface {
// Unmarshal parses the encoded bytes of the protobuf wire input.
// The provided buffer is only valid for during method call.
// It should not reset the receiver message.
Unmarshal([]byte) error
}
// Merger is implemented by messages that can merge themselves.
// This interface is used by the following functions: Clone and Merge.
//
// Deprecated: Do not implement.
type Merger interface {
// Merge merges the contents of src into the receiver message.
// It clones all data structures in src such that it aliases no mutable
// memory referenced by src.
Merge(src Message)
}
// RequiredNotSetError is an error type returned when
// marshaling or unmarshaling a message with missing required fields.
type RequiredNotSetError struct {
err error
}
func (e *RequiredNotSetError) Error() string {
if e.err != nil {
return e.err.Error()
}
return "proto: required field not set"
}
func (e *RequiredNotSetError) RequiredNotSet() bool {
return true
}
func checkRequiredNotSet(m proto.Message) error {
if err := proto.IsInitialized(m); err != nil {
return &RequiredNotSetError{err: err}
}
return nil
}
// Clone returns a deep copy of src.
func Clone(src Message) Message {
srcMsg := protoimpl.X.MessageOf(src)
if srcMsg == nil || !srcMsg.IsValid() {
return src
}
dst := protoimpl.X.ProtoMessageV1Of(srcMsg.New().Interface())
Merge(dst, src)
return dst
}
// Merge merges src into dst, which must be messages of the same type.
//
// Populated scalar fields in src are copied to dst, while populated
// singular messages in src are merged into dst by recursively calling Merge.
// The elements of every list field in src is appended to the corresponded
// list fields in dst. The entries of every map field in src is copied into
// the corresponding map field in dst, possibly replacing existing entries.
// The unknown fields of src are appended to the unknown fields of dst.
func Merge(dst, src Message) {
// TODO: Drop this type assertion if the aberrant wrapper in v2 calls this.
if m, ok := dst.(Merger); ok {
m.Merge(src)
return
}
proto.Merge(
protoimpl.X.ProtoMessageV2Of(dst),
protoimpl.X.ProtoMessageV2Of(src),
)
}
// Equal reports whether two messages are equal.
// If two messages marshal to the same bytes under deterministic serialization,
// then Equal is guaranteed to report true.
//
// Two messages are equal if they are the same protobuf message type,
// have the same set of populated known and extension field values,
// and the same set of unknown fields values.
//
// Scalar values are compared with the equivalent of the == operator in Go,
// except bytes values which are compared using bytes.Equal and
// floating point values which specially treat NaNs as equal.
// Message values are compared by recursively calling Equal.
// Lists are equal if each element value is also equal.
// Maps are equal if they have the same set of keys, where the pair of values
// for each key is also equal.
func Equal(x, y Message) bool {
return proto.Equal(
protoimpl.X.ProtoMessageV2Of(x),
protoimpl.X.ProtoMessageV2Of(y),
)
}
func isMessageSet(md protoreflect.MessageDescriptor) bool {
ms, ok := md.(interface{ IsMessageSet() bool })
return ok && ms.IsMessageSet()
}

Просмотреть файл

@ -1,99 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2014 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
option go_package = "github.com/golang/protobuf/proto/proto3_proto";
import "google/protobuf/any.proto";
import "test_proto/test.proto";
package proto3_proto;
message Message {
enum Humour {
UNKNOWN = 0;
PUNS = 1;
SLAPSTICK = 2;
BILL_BAILEY = 3;
}
string name = 1;
Humour hilarity = 2;
uint32 height_in_cm = 3;
bytes data = 4;
int64 result_count = 7;
bool true_scotsman = 8;
float score = 9;
repeated uint64 key = 5;
repeated int32 short_key = 19;
Nested nested = 6;
repeated Humour r_funny = 16;
map<string, Nested> terrain = 10;
test_proto.SubDefaults proto2_field = 11;
map<string, test_proto.SubDefaults> proto2_value = 13;
google.protobuf.Any anything = 14;
repeated google.protobuf.Any many_things = 15;
Message submessage = 17;
repeated Message children = 18;
map<string, string> string_map = 20;
}
message Nested {
string bunny = 1;
bool cute = 2;
}
message MessageWithMap {
map<bool, bytes> byte_mapping = 1;
}
message IntMap {
map<int32, int32> rtt = 1;
}
message IntMaps {
repeated IntMap maps = 1;
}
message TestUTF8 {
string scalar = 1;
repeated string vector = 2;
oneof oneof { string field = 3; }
map<string, int64> map_key = 4;
map<int64, string> map_value = 5;
}

Просмотреть файл

@ -1,124 +0,0 @@
// Copyright 2014 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.
package proto_test
import (
"bytes"
"testing"
"github.com/golang/protobuf/proto"
pb "github.com/golang/protobuf/proto/proto3_proto"
tpb "github.com/golang/protobuf/proto/test_proto"
)
func TestProto3ZeroValues(t *testing.T) {
tests := []struct {
desc string
m proto.Message
}{
{"zero message", &pb.Message{}},
{"empty bytes field", &pb.Message{Data: []byte{}}},
}
for _, test := range tests {
b, err := proto.Marshal(test.m)
if err != nil {
t.Errorf("%s: proto.Marshal: %v", test.desc, err)
continue
}
if len(b) > 0 {
t.Errorf("%s: Encoding is non-empty: %q", test.desc, b)
}
}
}
func TestRoundTripProto3(t *testing.T) {
m := &pb.Message{
Name: "David", // (2 | 1<<3): 0x0a 0x05 "David"
Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01
HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01
Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto"
ResultCount: 47, // (0 | 7<<3): 0x38 0x2f
TrueScotsman: true, // (0 | 8<<3): 0x40 0x01
Score: 8.1, // (5 | 9<<3): 0x4d <8.1>
Key: []uint64{1, 0xdeadbeef},
Nested: &pb.Nested{
Bunny: "Monty",
},
}
t.Logf(" m: %v", m)
b, err := proto.Marshal(m)
if err != nil {
t.Fatalf("proto.Marshal: %v", err)
}
t.Logf(" b: %q", b)
m2 := new(pb.Message)
if err := proto.Unmarshal(b, m2); err != nil {
t.Fatalf("proto.Unmarshal: %v", err)
}
t.Logf("m2: %v", m2)
if !proto.Equal(m, m2) {
t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2)
}
}
func TestGettersForBasicTypesExist(t *testing.T) {
var m pb.Message
if got := m.GetNested().GetBunny(); got != "" {
t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got)
}
if got := m.GetNested().GetCute(); got {
t.Errorf("m.GetNested().GetCute() = %t, want false", got)
}
}
func TestProto3SetDefaults(t *testing.T) {
in := &pb.Message{
Terrain: map[string]*pb.Nested{
"meadow": new(pb.Nested),
},
Proto2Field: new(tpb.SubDefaults),
Proto2Value: map[string]*tpb.SubDefaults{
"badlands": new(tpb.SubDefaults),
},
}
got := proto.Clone(in).(*pb.Message)
proto.SetDefaults(got)
// There are no defaults in proto3. Everything should be the zero value, but
// we need to remember to set defaults for nested proto2 messages.
want := &pb.Message{
Terrain: map[string]*pb.Nested{
"meadow": new(pb.Nested),
},
Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)},
Proto2Value: map[string]*tpb.SubDefaults{
"badlands": &tpb.SubDefaults{N: proto.Int64(7)},
},
}
if !proto.Equal(got, want) {
t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want)
}
}
func TestUnknownFieldPreservation(t *testing.T) {
b1 := "\x0a\x05David" // Known tag 1
b2 := "\xc2\x0c\x06Google" // Unknown tag 200
b := []byte(b1 + b2)
m := new(pb.Message)
if err := proto.Unmarshal(b, m); err != nil {
t.Fatalf("proto.Unmarshal: %v", err)
}
if !bytes.Equal(m.XXX_unrecognized, []byte(b2)) {
t.Fatalf("mismatching unknown fields:\ngot %q\nwant %q", m.XXX_unrecognized, b2)
}
}

Просмотреть файл

@ -9,48 +9,48 @@ import (
"github.com/golang/protobuf/proto"
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
pb "github.com/golang/protobuf/proto/test_proto"
pb2 "github.com/golang/protobuf/internal/testprotos/proto2_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
var cloneTestMessage = &pb.MyMessage{
var cloneTestMessage = &pb2.MyMessage{
Count: proto.Int32(42),
Name: proto.String("Dave"),
Pet: []string{"bunny", "kitty", "horsey"},
Inner: &pb.InnerMessage{
Inner: &pb2.InnerMessage{
Host: proto.String("niles"),
Port: proto.Int32(9099),
Connected: proto.Bool(true),
},
Others: []*pb.OtherMessage{
Others: []*pb2.OtherMessage{
{
Value: []byte("some bytes"),
},
},
Somegroup: &pb.MyMessage_SomeGroup{
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(6),
},
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
}
func init() {
ext := &pb.Ext{
ext := &pb2.Ext{
Data: proto.String("extension"),
}
if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil {
if err := proto.SetExtension(cloneTestMessage, pb2.E_Ext_More, ext); err != nil {
panic("SetExtension: " + err.Error())
}
if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_Text, proto.String("hello")); err != nil {
if err := proto.SetExtension(cloneTestMessage, pb2.E_Ext_Text, proto.String("hello")); err != nil {
panic("SetExtension: " + err.Error())
}
if err := proto.SetExtension(cloneTestMessage, pb.E_Greeting, []string{"one", "two"}); err != nil {
if err := proto.SetExtension(cloneTestMessage, pb2.E_Greeting, []string{"one", "two"}); err != nil {
panic("SetExtension: " + err.Error())
}
}
func TestClone(t *testing.T) {
// Create a clone using a marshal/unmarshal roundtrip.
vanilla := new(pb.MyMessage)
vanilla := new(pb2.MyMessage)
b, err := proto.Marshal(cloneTestMessage)
if err != nil {
t.Errorf("unexpected Marshal error: %v", err)
@ -60,26 +60,26 @@ func TestClone(t *testing.T) {
}
// Create a clone using Clone and verify that it is equal to the original.
m := proto.Clone(cloneTestMessage).(*pb.MyMessage)
m := proto.Clone(cloneTestMessage).(*pb2.MyMessage)
if !proto.Equal(m, cloneTestMessage) {
t.Fatalf("Clone(%v) = %v", cloneTestMessage, m)
}
// Mutate the clone, which should not affect the original.
x1, err := proto.GetExtension(m, pb.E_Ext_More)
x1, err := proto.GetExtension(m, pb2.E_Ext_More)
if err != nil {
t.Errorf("unexpected GetExtension(%v) error: %v", pb.E_Ext_More.Name, err)
t.Errorf("unexpected GetExtension(%v) error: %v", pb2.E_Ext_More.Name, err)
}
x2, err := proto.GetExtension(m, pb.E_Ext_Text)
x2, err := proto.GetExtension(m, pb2.E_Ext_Text)
if err != nil {
t.Errorf("unexpected GetExtension(%v) error: %v", pb.E_Ext_Text.Name, err)
t.Errorf("unexpected GetExtension(%v) error: %v", pb2.E_Ext_Text.Name, err)
}
x3, err := proto.GetExtension(m, pb.E_Greeting)
x3, err := proto.GetExtension(m, pb2.E_Greeting)
if err != nil {
t.Errorf("unexpected GetExtension(%v) error: %v", pb.E_Greeting.Name, err)
t.Errorf("unexpected GetExtension(%v) error: %v", pb2.E_Greeting.Name, err)
}
*m.Inner.Port++
*(x1.(*pb.Ext)).Data = "blah blah"
*(x1.(*pb2.Ext)).Data = "blah blah"
*(x2.(*string)) = "goodbye"
x3.([]string)[0] = "zero"
if !proto.Equal(cloneTestMessage, vanilla) {
@ -88,7 +88,7 @@ func TestClone(t *testing.T) {
}
func TestCloneNil(t *testing.T) {
var m *pb.MyMessage
var m *pb2.MyMessage
if c := proto.Clone(m); !proto.Equal(m, c) {
t.Errorf("Clone(%v) = %v", m, c)
}
@ -98,37 +98,37 @@ var mergeTests = []struct {
src, dst, want proto.Message
}{
{
src: &pb.MyMessage{
src: &pb2.MyMessage{
Count: proto.Int32(42),
},
dst: &pb.MyMessage{
dst: &pb2.MyMessage{
Name: proto.String("Dave"),
},
want: &pb.MyMessage{
want: &pb2.MyMessage{
Count: proto.Int32(42),
Name: proto.String("Dave"),
},
},
{
src: &pb.MyMessage{
Inner: &pb.InnerMessage{
src: &pb2.MyMessage{
Inner: &pb2.InnerMessage{
Host: proto.String("hey"),
Connected: proto.Bool(true),
},
Pet: []string{"horsey"},
Others: []*pb.OtherMessage{
Others: []*pb2.OtherMessage{
{
Value: []byte("some bytes"),
},
},
},
dst: &pb.MyMessage{
Inner: &pb.InnerMessage{
dst: &pb2.MyMessage{
Inner: &pb2.InnerMessage{
Host: proto.String("niles"),
Port: proto.Int32(9099),
},
Pet: []string{"bunny", "kitty"},
Others: []*pb.OtherMessage{
Others: []*pb2.OtherMessage{
{
Key: proto.Int64(31415926535),
},
@ -138,14 +138,14 @@ var mergeTests = []struct {
},
},
},
want: &pb.MyMessage{
Inner: &pb.InnerMessage{
want: &pb2.MyMessage{
Inner: &pb2.InnerMessage{
Host: proto.String("hey"),
Connected: proto.Bool(true),
Port: proto.Int32(9099),
},
Pet: []string{"bunny", "kitty", "horsey"},
Others: []*pb.OtherMessage{
Others: []*pb2.OtherMessage{
{
Key: proto.Int64(31415926535),
},
@ -157,17 +157,17 @@ var mergeTests = []struct {
},
},
{
src: &pb.MyMessage{
src: &pb2.MyMessage{
RepBytes: [][]byte{[]byte("wow")},
},
dst: &pb.MyMessage{
Somegroup: &pb.MyMessage_SomeGroup{
dst: &pb2.MyMessage{
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(6),
},
RepBytes: [][]byte{[]byte("sham")},
},
want: &pb.MyMessage{
Somegroup: &pb.MyMessage_SomeGroup{
want: &pb2.MyMessage{
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(6),
},
RepBytes: [][]byte{[]byte("sham"), []byte("wow")},
@ -175,41 +175,41 @@ var mergeTests = []struct {
},
// Check that a scalar bytes field replaces rather than appends.
{
src: &pb.OtherMessage{Value: []byte("foo")},
dst: &pb.OtherMessage{Value: []byte("bar")},
want: &pb.OtherMessage{Value: []byte("foo")},
src: &pb2.OtherMessage{Value: []byte("foo")},
dst: &pb2.OtherMessage{Value: []byte("bar")},
want: &pb2.OtherMessage{Value: []byte("foo")},
},
{
src: &pb.MessageWithMap{
src: &pb2.MessageWithMap{
NameMapping: map[int32]string{6: "Nigel"},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb.FloatingPoint{
MsgMapping: map[int64]*pb2.FloatingPoint{
0x4001: &pb2.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb2.FloatingPoint{
F: proto.Float64(2.0),
},
},
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
},
dst: &pb.MessageWithMap{
dst: &pb2.MessageWithMap{
NameMapping: map[int32]string{
6: "Bruce", // should be overwritten
7: "Andrew",
},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: &pb.FloatingPoint{
MsgMapping: map[int64]*pb2.FloatingPoint{
0x4002: &pb2.FloatingPoint{
F: proto.Float64(3.0),
Exact: proto.Bool(true),
}, // the entire message should be overwritten
},
},
want: &pb.MessageWithMap{
want: &pb2.MessageWithMap{
NameMapping: map[int32]string{
6: "Nigel",
7: "Andrew",
},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb.FloatingPoint{
MsgMapping: map[int64]*pb2.FloatingPoint{
0x4001: &pb2.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb2.FloatingPoint{
F: proto.Float64(2.0),
},
},
@ -219,83 +219,83 @@ var mergeTests = []struct {
// proto3 shouldn't merge zero values,
// in the same way that proto2 shouldn't merge nils.
{
src: &proto3pb.Message{
src: &pb3.Message{
Name: "Aaron",
Data: []byte(""), // zero value, but not nil
},
dst: &proto3pb.Message{
dst: &pb3.Message{
HeightInCm: 176,
Data: []byte("texas!"),
},
want: &proto3pb.Message{
want: &pb3.Message{
Name: "Aaron",
HeightInCm: 176,
Data: []byte("texas!"),
},
},
{ // Oneof fields should merge by assignment.
src: &pb.Communique{Union: &pb.Communique_Number{41}},
dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
want: &pb.Communique{Union: &pb.Communique_Number{41}},
src: &pb2.Communique{Union: &pb2.Communique_Number{41}},
dst: &pb2.Communique{Union: &pb2.Communique_Name{"Bobby Tables"}},
want: &pb2.Communique{Union: &pb2.Communique_Number{41}},
},
{ // Oneof nil is the same as not set.
src: &pb.Communique{},
dst: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
want: &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}},
src: &pb2.Communique{},
dst: &pb2.Communique{Union: &pb2.Communique_Name{"Bobby Tables"}},
want: &pb2.Communique{Union: &pb2.Communique_Name{"Bobby Tables"}},
},
{
src: &pb.Communique{Union: &pb.Communique_Number{1337}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Number{1337}},
src: &pb2.Communique{Union: &pb2.Communique_Number{1337}},
dst: &pb2.Communique{},
want: &pb2.Communique{Union: &pb2.Communique_Number{1337}},
},
{
src: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Col{pb.MyMessage_RED}},
src: &pb2.Communique{Union: &pb2.Communique_Col{pb2.MyMessage_RED}},
dst: &pb2.Communique{},
want: &pb2.Communique{Union: &pb2.Communique_Col{pb2.MyMessage_RED}},
},
{
src: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Data{[]byte("hello")}},
src: &pb2.Communique{Union: &pb2.Communique_Data{[]byte("hello")}},
dst: &pb2.Communique{},
want: &pb2.Communique{Union: &pb2.Communique_Data{[]byte("hello")}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}},
src: &pb2.Communique{Union: &pb2.Communique_Msg{&pb2.Strings{BytesField: []byte{1, 2, 3}}}},
dst: &pb2.Communique{},
want: &pb2.Communique{Union: &pb2.Communique_Msg{&pb2.Strings{BytesField: []byte{1, 2, 3}}}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{}},
dst: &pb.Communique{},
want: &pb.Communique{Union: &pb.Communique_Msg{}},
src: &pb2.Communique{Union: &pb2.Communique_Msg{}},
dst: &pb2.Communique{},
want: &pb2.Communique{Union: &pb2.Communique_Msg{}},
},
{
src: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123")}}},
dst: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{BytesField: []byte{1, 2, 3}}}},
want: &pb.Communique{Union: &pb.Communique_Msg{&pb.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}},
src: &pb2.Communique{Union: &pb2.Communique_Msg{&pb2.Strings{StringField: proto.String("123")}}},
dst: &pb2.Communique{Union: &pb2.Communique_Msg{&pb2.Strings{BytesField: []byte{1, 2, 3}}}},
want: &pb2.Communique{Union: &pb2.Communique_Msg{&pb2.Strings{StringField: proto.String("123"), BytesField: []byte{1, 2, 3}}}},
},
{
src: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Cute: true}, // replace
"kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert
src: &pb3.Message{
Terrain: map[string]*pb3.Nested{
"kay_a": &pb3.Nested{Cute: true}, // replace
"kay_b": &pb3.Nested{Bunny: "rabbit"}, // insert
},
},
dst: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Bunny: "lost"}, // replaced
"kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep
dst: &pb3.Message{
Terrain: map[string]*pb3.Nested{
"kay_a": &pb3.Nested{Bunny: "lost"}, // replaced
"kay_c": &pb3.Nested{Bunny: "bunny"}, // keep
},
},
want: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Cute: true},
"kay_b": &proto3pb.Nested{Bunny: "rabbit"},
"kay_c": &proto3pb.Nested{Bunny: "bunny"},
want: &pb3.Message{
Terrain: map[string]*pb3.Nested{
"kay_a": &pb3.Nested{Cute: true},
"kay_b": &pb3.Nested{Bunny: "rabbit"},
"kay_c": &pb3.Nested{Bunny: "bunny"},
},
},
},
{
src: &pb.GoTest{
src: &pb2.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
@ -306,8 +306,8 @@ var mergeTests = []struct {
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
dst: &pb.GoTest{},
want: &pb.GoTest{
dst: &pb2.GoTest{},
want: &pb2.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
@ -320,8 +320,8 @@ var mergeTests = []struct {
},
},
{
src: &pb.GoTest{},
dst: &pb.GoTest{
src: &pb2.GoTest{},
dst: &pb2.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
@ -332,7 +332,7 @@ var mergeTests = []struct {
F_StringRepeated: []string{},
F_BytesRepeated: [][]byte{},
},
want: &pb.GoTest{
want: &pb2.GoTest{
F_BoolRepeated: []bool{},
F_Int32Repeated: []int32{},
F_Int64Repeated: []int64{},
@ -345,21 +345,21 @@ var mergeTests = []struct {
},
},
{
src: &pb.GoTest{
src: &pb2.GoTest{
F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}},
},
dst: &pb.GoTest{},
want: &pb.GoTest{
dst: &pb2.GoTest{},
want: &pb2.GoTest{
F_BytesRepeated: [][]byte{nil, []byte{}, []byte{0}},
},
},
{
src: &pb.MyMessage{
Others: []*pb.OtherMessage{},
src: &pb2.MyMessage{
Others: []*pb2.OtherMessage{},
},
dst: &pb.MyMessage{},
want: &pb.MyMessage{
Others: []*pb.OtherMessage{},
dst: &pb2.MyMessage{},
want: &pb2.MyMessage{
Others: []*pb2.OtherMessage{},
},
},
}

218
proto/proto_equal_test.go Normal file
Просмотреть файл

@ -0,0 +1,218 @@
// Copyright 2011 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.
package proto_test
import (
"testing"
"github.com/golang/protobuf/proto"
pb2 "github.com/golang/protobuf/internal/testprotos/proto2_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
// Four identical base messages.
// The init function adds extensions to some of them.
var messageWithoutExtension = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension1a = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension1b = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension2 = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension3a = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension3b = &pb2.MyMessage{Count: proto.Int32(7)}
var messageWithExtension3c = &pb2.MyMessage{Count: proto.Int32(7)}
// Two messages with non-message extensions.
var messageWithInt32Extension1 = &pb2.MyMessage{Count: proto.Int32(8)}
var messageWithInt32Extension2 = &pb2.MyMessage{Count: proto.Int32(8)}
func init() {
ext1 := &pb2.Ext{Data: proto.String("Kirk")}
ext2 := &pb2.Ext{Data: proto.String("Picard")}
// messageWithExtension1a has ext1, but never marshals it.
if err := proto.SetExtension(messageWithExtension1a, pb2.E_Ext_More, ext1); err != nil {
panic("proto.SetExtension on 1a failed: " + err.Error())
}
// messageWithExtension1b is the unmarshaled form of messageWithExtension1a.
if err := proto.SetExtension(messageWithExtension1b, pb2.E_Ext_More, ext1); err != nil {
panic("proto.SetExtension on 1b failed: " + err.Error())
}
buf, err := proto.Marshal(messageWithExtension1b)
if err != nil {
panic("proto.Marshal of 1b failed: " + err.Error())
}
messageWithExtension1b.Reset()
if err := proto.Unmarshal(buf, messageWithExtension1b); err != nil {
panic("proto.Unmarshal of 1b failed: " + err.Error())
}
// messageWithExtension2 has ext2.
if err := proto.SetExtension(messageWithExtension2, pb2.E_Ext_More, ext2); err != nil {
panic("proto.SetExtension on 2 failed: " + err.Error())
}
if err := proto.SetExtension(messageWithInt32Extension1, pb2.E_Ext_Number, proto.Int32(23)); err != nil {
panic("proto.SetExtension on Int32-1 failed: " + err.Error())
}
if err := proto.SetExtension(messageWithInt32Extension1, pb2.E_Ext_Number, proto.Int32(24)); err != nil {
panic("proto.SetExtension on Int32-2 failed: " + err.Error())
}
// messageWithExtension3{a,b,c} has unregistered extension.
if proto.RegisteredExtensions(messageWithExtension3a)[200] != nil {
panic("expect extension 200 unregistered")
}
bytes := []byte{
0xc0, 0x0c, 0x01, // id=200, wiretype=0 (varint), data=1
}
bytes2 := []byte{
0xc0, 0x0c, 0x02, // id=200, wiretype=0 (varint), data=2
}
proto.SetRawExtension(messageWithExtension3a, 200, bytes)
proto.SetRawExtension(messageWithExtension3b, 200, bytes)
proto.SetRawExtension(messageWithExtension3c, 200, bytes2)
}
var EqualTests = []struct {
desc string
a, b proto.Message
exp bool
}{
{"different types", &pb2.GoEnum{}, &pb2.GoTestField{}, false},
{"equal empty", &pb2.GoEnum{}, &pb2.GoEnum{}, true},
{"nil vs nil", nil, nil, true},
{"typed nil vs typed nil", (*pb2.GoEnum)(nil), (*pb2.GoEnum)(nil), true},
{"typed nil vs empty", (*pb2.GoEnum)(nil), &pb2.GoEnum{}, false},
{"different typed nil", (*pb2.GoEnum)(nil), (*pb2.GoTestField)(nil), false},
{"one set field, one unset field", &pb2.GoTestField{Label: proto.String("foo")}, &pb2.GoTestField{}, false},
{"one set field zero, one unset field", &pb2.GoTest{Param: proto.Int32(0)}, &pb2.GoTest{}, false},
{"different set fields", &pb2.GoTestField{Label: proto.String("foo")}, &pb2.GoTestField{Label: proto.String("bar")}, false},
{"equal set", &pb2.GoTestField{Label: proto.String("foo")}, &pb2.GoTestField{Label: proto.String("foo")}, true},
{"repeated, one set", &pb2.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb2.GoTest{}, false},
{"repeated, different length", &pb2.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb2.GoTest{F_Int32Repeated: []int32{2}}, false},
{"repeated, different value", &pb2.GoTest{F_Int32Repeated: []int32{2}}, &pb2.GoTest{F_Int32Repeated: []int32{3}}, false},
{"repeated, equal", &pb2.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb2.GoTest{F_Int32Repeated: []int32{2, 4}}, true},
{"repeated, nil equal nil", &pb2.GoTest{F_Int32Repeated: nil}, &pb2.GoTest{F_Int32Repeated: nil}, true},
{"repeated, nil equal empty", &pb2.GoTest{F_Int32Repeated: nil}, &pb2.GoTest{F_Int32Repeated: []int32{}}, true},
{"repeated, empty equal nil", &pb2.GoTest{F_Int32Repeated: []int32{}}, &pb2.GoTest{F_Int32Repeated: nil}, true},
{
"nested, different",
&pb2.GoTest{RequiredField: &pb2.GoTestField{Label: proto.String("foo")}},
&pb2.GoTest{RequiredField: &pb2.GoTestField{Label: proto.String("bar")}},
false,
},
{
"nested, equal",
&pb2.GoTest{RequiredField: &pb2.GoTestField{Label: proto.String("wow")}},
&pb2.GoTest{RequiredField: &pb2.GoTestField{Label: proto.String("wow")}},
true,
},
{"bytes", &pb2.OtherMessage{Value: []byte("foo")}, &pb2.OtherMessage{Value: []byte("foo")}, true},
{"bytes, empty", &pb2.OtherMessage{Value: []byte{}}, &pb2.OtherMessage{Value: []byte{}}, true},
{"bytes, empty vs nil", &pb2.OtherMessage{Value: []byte{}}, &pb2.OtherMessage{Value: nil}, false},
{
"repeated bytes",
&pb2.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
&pb2.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}},
true,
},
// In proto3, []byte{} and []byte(nil) are equal.
{"proto3 bytes, empty vs nil", &pb3.Message{Data: []byte{}}, &pb3.Message{Data: nil}, true},
{"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false},
{"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true},
{"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false},
{"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true},
{"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false},
{"unregistered extension same", messageWithExtension3a, messageWithExtension3b, true},
{"unregistered extension different", messageWithExtension3a, messageWithExtension3c, false},
{
"message with group",
&pb2.MyMessage{
Count: proto.Int32(1),
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(5),
},
},
&pb2.MyMessage{
Count: proto.Int32(1),
Somegroup: &pb2.MyMessage_SomeGroup{
GroupField: proto.Int32(5),
},
},
true,
},
{
"map same",
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
true,
},
{
"map different entry",
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb2.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}},
false,
},
{
"map different key only",
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb2.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}},
false,
},
{
"map different value only",
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}},
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}},
false,
},
{
"zero-length maps same",
&pb2.MessageWithMap{NameMapping: map[int32]string{}},
&pb2.MessageWithMap{NameMapping: nil},
true,
},
{
"orders in map don't matter",
&pb2.MessageWithMap{NameMapping: map[int32]string{1: "Ken", 2: "Rob"}},
&pb2.MessageWithMap{NameMapping: map[int32]string{2: "Rob", 1: "Ken"}},
true,
},
{
"oneof same",
&pb2.Communique{Union: &pb2.Communique_Number{41}},
&pb2.Communique{Union: &pb2.Communique_Number{41}},
true,
},
{
"oneof one nil",
&pb2.Communique{Union: &pb2.Communique_Number{41}},
&pb2.Communique{},
false,
},
{
"oneof different",
&pb2.Communique{Union: &pb2.Communique_Number{41}},
&pb2.Communique{Union: &pb2.Communique_Name{"Bobby Tables"}},
false,
},
}
func TestEqual(t *testing.T) {
for _, tc := range EqualTests {
if res := proto.Equal(tc.a, tc.b); res != tc.exp {
t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp)
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,166 +1,323 @@
// Copyright 2018 The Go Authors. All rights reserved.
// 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.
package proto
import (
"bytes"
"compress/gzip"
"fmt"
"log"
"io/ioutil"
"reflect"
"strconv"
"strings"
"sync"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
var enumValueMaps = make(map[string]map[string]int32)
// filePath is the path to the proto source file.
type filePath = string // e.g., "google/protobuf/descriptor.proto"
// RegisterEnum is called from the generated code to install the enum descriptor
// maps into the global table to aid parsing text format protocol buffers.
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
if registerEnumAlt != nil {
registerEnumAlt(typeName, unusedNameMap, valueMap) // populated by hooks_enabled.go
return
// fileDescGZIP is the compressed contents of the encoded FileDescriptorProto.
type fileDescGZIP = []byte
var fileCache sync.Map // map[filePath]fileDescGZIP
// RegisterFile is called from generated code to register the compressed
// FileDescriptorProto with the file path for a proto source file.
//
// Deprecated: Use protoregistry.GlobalFiles.Register instead.
func RegisterFile(s filePath, d fileDescGZIP) {
// Decompress the descriptor.
zr, err := gzip.NewReader(bytes.NewReader(d))
if err != nil {
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
}
if _, ok := enumValueMaps[typeName]; ok {
panic("proto: duplicate enum registered: " + typeName)
b, err := ioutil.ReadAll(zr)
if err != nil {
panic(fmt.Sprintf("proto: invalid compressed file descriptor: %v", err))
}
enumValueMaps[typeName] = valueMap
// Construct a protoreflect.FileDescriptor from the raw descriptor.
// Note that DescBuilder.Build automatically registers the constructed
// file descriptor with the v2 registry.
protoimpl.DescBuilder{RawDescriptor: b}.Build()
// Locally cache the raw descriptor form for the file.
fileCache.Store(s, d)
}
// EnumValueMap returns the mapping from names to integers of the
// enum type enumType, or a nil if not found.
func EnumValueMap(enumType string) map[string]int32 {
if enumValueMapAlt != nil {
return enumValueMapAlt(enumType) // populated by hooks_enabled.go
// FileDescriptor returns the compressed FileDescriptorProto given the file path
// for a proto source file. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalFiles.RangeFilesByPath instead.
func FileDescriptor(s filePath) fileDescGZIP {
if v, ok := fileCache.Load(s); ok {
return v.(fileDescGZIP)
}
return enumValueMaps[enumType]
// Find the descriptor in the v2 registry.
var b []byte
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok {
b = fd.ProtoLegacyRawDesc()
} else {
// TODO: Use protodesc.ToFileDescriptorProto to construct
// a descriptorpb.FileDescriptorProto and marshal it.
// However, doing so causes the proto package to have a dependency
// on descriptorpb, leading to cyclic dependency issues.
}
}
// Locally cache the raw descriptor form for the file.
if len(b) > 0 {
v, _ := fileCache.LoadOrStore(s, protoimpl.X.CompressGZIP(b))
return v.(fileDescGZIP)
}
return nil
}
// A registry of all linked message types.
// The string is a fully-qualified proto name ("pkg.Message").
var (
protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
revProtoTypes = make(map[reflect.Type]string)
)
// enumName is the name of an enum. For historical reasons, the enum name is
// neither the full Go name nor the full protobuf name of the enum.
// The name is the dot-separated combination of just the proto package that the
// enum is declared within followed by the Go type name of the generated enum.
type enumName = string // e.g., "my.proto.package.GoMessage_GoEnum"
// RegisterType is called from generated code and maps from the fully qualified
// proto name to the type (pointer to struct) of the protocol buffer.
func RegisterType(x Message, name string) {
if registerTypeAlt != nil {
registerTypeAlt(x, name) // populated by hooks_enabled.go
return
// enumsByName maps enum values by name to their numeric counterpart.
type enumsByName = map[string]int32
// enumsByNumber maps enum values by number to their name counterpart.
type enumsByNumber = map[int32]string
var enumCache sync.Map // map[enumName]enumsByName
var numFilesCache sync.Map // map[protoreflect.FullName]int
// RegisterEnum is called from the generated code to register the mapping of
// enum value names to enum numbers for the enum identified by s.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterEnum(s enumName, _ enumsByNumber, m enumsByName) {
if _, ok := enumCache.Load(s); ok {
panic("proto: duplicate enum registered: " + s)
}
if _, ok := protoTypedNils[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
// Generated code always calls RegisterType with nil x.
// This check is just for extra safety.
protoTypedNils[name] = x
} else {
protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
}
revProtoTypes[t] = name
enumCache.Store(s, m)
// This does not forward registration to the v2 registry since this API
// lacks sufficient information to construct a complete v2 enum descriptor.
}
// RegisterMapType is called from generated code and maps from the fully qualified
// proto name to the native map type of the proto map definition.
func RegisterMapType(x interface{}, name string) {
if registerMapTypeAlt != nil {
registerMapTypeAlt(x, name) // populated by hooks_enabled.go
return
// EnumValueMap returns the mapping from enum value names to enum numbers for
// the enum of the given name. It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindEnumByName instead.
func EnumValueMap(s enumName) enumsByName {
if v, ok := enumCache.Load(s); ok {
return v.(enumsByName)
}
if reflect.TypeOf(x).Kind() != reflect.Map {
panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
}
if _, ok := protoMapTypes[name]; ok {
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
protoMapTypes[name] = t
// Avoid registering into revProtoTypes since map types are not unique.
// revProtoTypes[t] = name
// Check whether the cache is stale. If the number of files in the current
// package differs, then it means that some enums may have been recently
// registered upstream that we do not know about.
var protoPkg protoreflect.FullName
if i := strings.LastIndexByte(s, '.'); i >= 0 {
protoPkg = protoreflect.FullName(s[:i])
}
v, _ := numFilesCache.Load(protoPkg)
numFiles, _ := v.(int)
if protoregistry.GlobalFiles.NumFilesByPackage(protoPkg) == numFiles {
return nil // cache is up-to-date; was not found earlier
}
// Update the enum cache for all enums declared in the given proto package.
numFiles = 0
protoregistry.GlobalFiles.RangeFilesByPackage(protoPkg, func(fd protoreflect.FileDescriptor) bool {
walkEnums(fd, func(ed protoreflect.EnumDescriptor) {
name := protoimpl.X.LegacyEnumName(ed)
if _, ok := enumCache.Load(name); !ok {
m := make(enumsByName)
evs := ed.Values()
for i := evs.Len() - 1; i >= 0; i-- {
ev := evs.Get(i)
m[string(ev.Name())] = int32(ev.Number())
}
enumCache.LoadOrStore(name, m)
}
})
numFiles++
return true
})
numFilesCache.Store(protoPkg, numFiles)
// Check cache again for enum map.
if v, ok := enumCache.Load(s); ok {
return v.(enumsByName)
}
return nil
}
// MessageName returns the fully-qualified proto name for the given message type.
func MessageName(x Message) string {
if messageNameAlt != nil {
return messageNameAlt(x) // populated by hooks_enabled.go
// walkEnums recursively walks all enums declared in d.
func walkEnums(d interface {
Enums() protoreflect.EnumDescriptors
Messages() protoreflect.MessageDescriptors
}, f func(protoreflect.EnumDescriptor)) {
eds := d.Enums()
for i := eds.Len() - 1; i >= 0; i-- {
f(eds.Get(i))
}
type xname interface {
XXX_MessageName() string
mds := d.Messages()
for i := mds.Len() - 1; i >= 0; i-- {
walkEnums(mds.Get(i), f)
}
if m, ok := x.(xname); ok {
}
// messageName is the full name of protobuf message.
type messageName = string
var messageTypeCache sync.Map // map[messageName]reflect.Type
// RegisterType is called from generated code to register the message Go type
// for a message of the given name.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterType(m Message, s messageName) {
mt := protoimpl.X.LegacyMessageTypeOf(m, protoreflect.FullName(s))
if err := protoregistry.GlobalTypes.RegisterMessage(mt); err != nil {
panic(err)
}
messageTypeCache.Store(s, reflect.TypeOf(m))
}
// RegisterMapType is called from generated code to register the Go map type
// for a protobuf message representing a map entry.
//
// Deprecated: Do not use.
func RegisterMapType(m interface{}, s messageName) {
t := reflect.TypeOf(m)
if t.Kind() != reflect.Map {
panic(fmt.Sprintf("invalid map kind: %v", t))
}
if _, ok := messageTypeCache.Load(s); ok {
panic(fmt.Errorf("proto: duplicate proto message registered: %s", s))
}
messageTypeCache.Store(s, t)
}
// MessageType returns the message type for a named message.
// It returns nil if not found.
//
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead.
func MessageType(s messageName) reflect.Type {
if v, ok := messageTypeCache.Load(s); ok {
return v.(reflect.Type)
}
// Derive the message type from the v2 registry.
var t reflect.Type
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(s)); mt != nil {
t = messageGoType(mt)
}
// If we could not get a concrete type, it is possible that it is a
// pseudo-message for a map entry.
if t == nil {
d, _ := protoregistry.GlobalFiles.FindDescriptorByName(protoreflect.FullName(s))
if md, _ := d.(protoreflect.MessageDescriptor); md != nil && md.IsMapEntry() {
kt := goTypeForField(md.Fields().ByNumber(1))
vt := goTypeForField(md.Fields().ByNumber(2))
t = reflect.MapOf(kt, vt)
}
}
// Locally cache the message type for the given name.
if t != nil {
v, _ := messageTypeCache.LoadOrStore(s, t)
return v.(reflect.Type)
}
return nil
}
func goTypeForField(fd protoreflect.FieldDescriptor) reflect.Type {
switch k := fd.Kind(); k {
case protoreflect.EnumKind:
if et, _ := protoregistry.GlobalTypes.FindEnumByName(fd.Enum().FullName()); et != nil {
return enumGoType(et)
}
return reflect.TypeOf(protoreflect.EnumNumber(0))
case protoreflect.MessageKind, protoreflect.GroupKind:
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()); mt != nil {
return messageGoType(mt)
}
return reflect.TypeOf((*protoreflect.Message)(nil)).Elem()
default:
return reflect.TypeOf(fd.Default().Interface())
}
}
func enumGoType(et protoreflect.EnumType) reflect.Type {
return reflect.TypeOf(et.New(0))
}
func messageGoType(mt protoreflect.MessageType) reflect.Type {
return reflect.TypeOf(protoimpl.X.ProtoMessageV1Of(mt.New().Interface()))
}
// MessageName returns the full protobuf name for the given message type.
//
// Deprecated: Use protoreflect.MessageDescriptor.FullName instead.
func MessageName(m Message) messageName {
if m == nil {
return ""
}
if m, ok := m.(interface{ XXX_MessageName() messageName }); ok {
return m.XXX_MessageName()
}
return revProtoTypes[reflect.TypeOf(x)]
return messageName(protoimpl.X.MessageDescriptorOf(m).FullName())
}
// MessageType returns the message type (pointer to struct) for a named message.
// The type is not guaranteed to implement proto.Message if the name refers to a
// map entry.
func MessageType(name string) reflect.Type {
if messageTypeAlt != nil {
return messageTypeAlt(name) // populated by hooks_enabled.go
// RegisterExtension is called from the generated code to register
// the extension descriptor.
//
// Deprecated: Use protoregistry.GlobalTypes.Register instead.
func RegisterExtension(d *ExtensionDesc) {
if err := protoregistry.GlobalTypes.RegisterExtension(d); err != nil {
panic(err)
}
if t, ok := protoTypedNils[name]; ok {
return reflect.TypeOf(t)
}
return protoMapTypes[name]
}
// A registry of all linked proto files.
var protoFiles = make(map[string][]byte) // file name => fileDescriptor
type extensionsByNumber = map[int32]*ExtensionDesc
// RegisterFile is called from generated code and maps from the
// full file name of a .proto file to its compressed FileDescriptorProto.
func RegisterFile(filename string, fileDescriptor []byte) {
if registerFileAlt != nil {
registerFileAlt(filename, fileDescriptor) // populated by hooks_enabled.go
return
var extensionCache sync.Map // map[messageName]extensionsByNumber
// RegisteredExtensions returns a map of the registered extensions for the
// provided protobuf message, indexed by the extension field number.
//
// Deprecated: Use protoregistry.GlobalTypes.RangeExtensionsByMessage instead.
func RegisteredExtensions(m Message) extensionsByNumber {
// Check whether the cache is stale. If the number of extensions for
// the given message differs, then it means that some extensions were
// recently registered upstream that we do not know about.
s := MessageName(m)
v, _ := extensionCache.Load(s)
xs, _ := v.(extensionsByNumber)
if protoregistry.GlobalTypes.NumExtensionsByMessage(protoreflect.FullName(s)) == len(xs) {
return xs // cache is up-to-date
}
protoFiles[filename] = fileDescriptor
}
// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
func FileDescriptor(filename string) []byte {
if fileDescriptorAlt != nil {
return fileDescriptorAlt(filename) // populated by hooks_enabled.go
}
return protoFiles[filename]
}
var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
// RegisterExtension is called from the generated code.
func RegisterExtension(desc *ExtensionDesc) {
if registerExtensionAlt != nil {
registerExtensionAlt(desc) // populated by hooks_enabled.go
return
}
st := reflect.TypeOf(desc.ExtendedType).Elem()
m := extensionMaps[st]
if m == nil {
m = make(map[int32]*ExtensionDesc)
extensionMaps[st] = m
}
if _, ok := m[desc.Field]; ok {
panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
}
m[desc.Field] = desc
}
// RegisteredExtensions returns a map of the registered extensions of a
// protocol buffer struct, indexed by the extension number.
// The argument pb should be a nil pointer to the struct type.
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
if registeredExtensionsAlt != nil {
return registeredExtensionsAlt(pb) // populated by hooks_enabled.go
}
return extensionMaps[reflect.TypeOf(pb).Elem()]
// Cache is stale, re-compute the extensions map.
xs = make(extensionsByNumber)
protoregistry.GlobalTypes.RangeExtensionsByMessage(protoreflect.FullName(s), func(xt protoreflect.ExtensionType) bool {
if xd, ok := xt.(*ExtensionDesc); ok {
xs[int32(xt.TypeDescriptor().Number())] = xd
} else {
// TODO: This implies that the protoreflect.ExtensionType is a
// custom type not generated by protoc-gen-go. We could try and
// convert the type to an ExtensionDesc.
}
return true
})
extensionCache.Store(s, xs)
return xs
}

Просмотреть файл

@ -9,20 +9,29 @@ import (
"testing"
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
func TestRegistry(t *testing.T) {
if got := proto.FileDescriptor("google/protobuf/descriptor.proto"); len(got) == 0 {
t.Errorf(`FileDescriptor("google/protobuf/descriptor.proto") = empty, want non-empty`)
file := new(descpb.DescriptorProto).ProtoReflect().Descriptor().ParentFile()
path := file.Path()
pkg := file.Package()
if got := proto.FileDescriptor(path); len(got) == 0 {
t.Errorf("FileDescriptor(%q) = empty, want non-empty", path)
}
if got := proto.EnumValueMap("google.protobuf.FieldDescriptorProto_Label"); len(got) == 0 {
t.Errorf(`EnumValueMap("google.protobuf.FieldDescriptorProto_Label") = empty, want non-empty`)
name := protoreflect.FullName(pkg + ".FieldDescriptorProto_Label")
if got := proto.EnumValueMap(string(name)); len(got) == 0 {
t.Errorf("EnumValueMap(%q) = empty, want non-empty", name)
}
wantType := reflect.TypeOf(new(descriptorpb.EnumDescriptorProto_EnumReservedRange))
gotType := proto.MessageType("google.protobuf.EnumDescriptorProto.EnumReservedRange")
msg := new(descpb.EnumDescriptorProto_EnumReservedRange)
name = msg.ProtoReflect().Descriptor().FullName()
wantType := reflect.TypeOf(msg)
gotType := proto.MessageType(string(name))
if gotType != wantType {
t.Errorf(`MessageType("google.protobuf.EnumDescriptorProto.EnumReservedRange") = %v, want %v`, gotType, wantType)
t.Errorf("MessageType(%q) = %v, want %v", name, gotType, wantType)
}
}

Просмотреть файл

@ -1,37 +0,0 @@
// Copyright 2012 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.
package proto
import (
"math"
"testing"
)
// This is a separate file and package from size_test.go because that one uses
// generated messages and thus may not be in package proto without having a circular
// dependency, whereas this file tests unexported details of size.go.
func TestVarintSize(t *testing.T) {
// Check the edge cases carefully.
testCases := []struct {
n uint64
size int
}{
{0, 1},
{1, 1},
{127, 1},
{128, 2},
{16383, 2},
{16384, 3},
{math.MaxInt64, 9},
{math.MaxInt64 + 1, 10},
}
for _, tc := range testCases {
size := SizeVarint(tc.n)
if size != tc.size {
t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size)
}
}
}

Просмотреть файл

@ -1,164 +0,0 @@
// Copyright 2012 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.
package proto_test
import (
"log"
"strings"
"testing"
. "github.com/golang/protobuf/proto"
proto3pb "github.com/golang/protobuf/proto/proto3_proto"
pb "github.com/golang/protobuf/proto/test_proto"
)
var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)}
// messageWithExtension2 is in equal_test.go.
var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)}
func init() {
if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil {
log.Panicf("SetExtension: %v", err)
}
if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil {
log.Panicf("SetExtension: %v", err)
}
// Force messageWithExtension3 to have the extension encoded.
Marshal(messageWithExtension3)
}
// non-pointer custom message
type nonptrMessage struct{}
func (m nonptrMessage) ProtoMessage() {}
func (m nonptrMessage) Reset() {}
func (m nonptrMessage) String() string { return "" }
func (m nonptrMessage) Marshal() ([]byte, error) {
return []byte{42}, nil
}
// custom message embedding a proto.Message
type messageWithEmbedding struct {
*pb.OtherMessage
}
func (m *messageWithEmbedding) ProtoMessage() {}
func (m *messageWithEmbedding) Reset() {}
func (m *messageWithEmbedding) String() string { return "" }
func (m *messageWithEmbedding) Marshal() ([]byte, error) {
return []byte{42}, nil
}
var SizeTests = []struct {
desc string
pb Message
}{
{"empty", &pb.OtherMessage{}},
// Basic types.
{"bool", &pb.Defaults{F_Bool: Bool(true)}},
{"int32", &pb.Defaults{F_Int32: Int32(12)}},
{"negative int32", &pb.Defaults{F_Int32: Int32(-1)}},
{"small int64", &pb.Defaults{F_Int64: Int64(1)}},
{"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}},
{"negative int64", &pb.Defaults{F_Int64: Int64(-1)}},
{"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}},
{"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}},
{"uint32", &pb.Defaults{F_Uint32: Uint32(123)}},
{"uint64", &pb.Defaults{F_Uint64: Uint64(124)}},
{"float", &pb.Defaults{F_Float: Float32(12.6)}},
{"double", &pb.Defaults{F_Double: Float64(13.9)}},
{"string", &pb.Defaults{F_String: String("niles")}},
{"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}},
{"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}},
{"sint32", &pb.Defaults{F_Sint32: Int32(65)}},
{"sint64", &pb.Defaults{F_Sint64: Int64(67)}},
{"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}},
// Repeated.
{"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}},
{"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}},
{"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}},
{"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}},
{"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}},
{"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{
// Need enough large numbers to verify that the header is counting the number of bytes
// for the field, not the number of elements.
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
}}},
{"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}},
{"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}},
// Nested.
{"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}},
{"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}},
// Other things.
{"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}},
{"extension (unencoded)", messageWithExtension1},
{"extension (encoded)", messageWithExtension3},
// proto3 message
{"proto3 empty", &proto3pb.Message{}},
{"proto3 bool", &proto3pb.Message{TrueScotsman: true}},
{"proto3 int64", &proto3pb.Message{ResultCount: 1}},
{"proto3 uint32", &proto3pb.Message{HeightInCm: 123}},
{"proto3 float", &proto3pb.Message{Score: 12.6}},
{"proto3 string", &proto3pb.Message{Name: "Snezana"}},
{"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}},
{"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}},
{"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}},
{"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}},
{"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}},
{"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}},
{"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}},
{"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
{"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
{"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
{"oneof not set", &pb.Oneof{}},
{"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}},
{"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}},
{"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}},
{"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}},
{"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}},
{"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}},
{"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}},
{"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}},
{"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}},
{"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}},
{"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}},
{"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}},
{"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}},
{"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}},
{"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}},
{"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}},
{"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}},
{"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}},
{"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}},
{"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}},
{"non-pointer message", nonptrMessage{}},
{"custom message with embedding", &messageWithEmbedding{&pb.OtherMessage{}}},
}
func TestSize(t *testing.T) {
for _, tc := range SizeTests {
size := Size(tc.pb)
b, err := Marshal(tc.pb)
if err != nil {
t.Errorf("%v: Marshal failed: %v", tc.desc, err)
continue
}
if size != len(b) {
t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b))
t.Logf("%v: bytes: %#v", tc.desc, b)
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,630 +0,0 @@
// Copyright 2016 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.
package proto
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
// Merge merges the src message into dst.
// This assumes that dst and src of the same type and are non-nil.
func (a *InternalMessageInfo) Merge(dst, src Message) {
mi := atomicLoadMergeInfo(&a.merge)
if mi == nil {
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
atomicStoreMergeInfo(&a.merge, mi)
}
mi.merge(toPointer(&dst), toPointer(&src))
}
type mergeInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []mergeFieldInfo
unrecognized field // Offset of XXX_unrecognized
}
type mergeFieldInfo struct {
field field // Offset of field, guaranteed to be valid
// isPointer reports whether the value in the field is a pointer.
// This is true for the following situations:
// * Pointer to struct
// * Pointer to basic type (proto2 only)
// * Slice (first value in slice header is a pointer)
// * String (first value in string header is a pointer)
isPointer bool
// basicWidth reports the width of the field assuming that it is directly
// embedded in the struct (as is the case for basic types in proto3).
// The possible values are:
// 0: invalid
// 1: bool
// 4: int32, uint32, float32
// 8: int64, uint64, float64
basicWidth int
// Where dst and src are pointers to the types being merged.
merge func(dst, src pointer)
}
var (
mergeInfoMap = map[reflect.Type]*mergeInfo{}
mergeInfoLock sync.Mutex
)
func getMergeInfo(t reflect.Type) *mergeInfo {
mergeInfoLock.Lock()
defer mergeInfoLock.Unlock()
mi := mergeInfoMap[t]
if mi == nil {
mi = &mergeInfo{typ: t}
mergeInfoMap[t] = mi
}
return mi
}
// merge merges src into dst assuming they are both of type *mi.typ.
func (mi *mergeInfo) merge(dst, src pointer) {
if dst.isNil() {
panic("proto: nil destination")
}
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&mi.initialized) == 0 {
mi.computeMergeInfo()
}
for _, fi := range mi.fields {
sfp := src.offset(fi.field)
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
continue
}
if fi.basicWidth > 0 {
switch {
case fi.basicWidth == 1 && !*sfp.toBool():
continue
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
continue
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
continue
}
}
}
dfp := dst.offset(fi.field)
fi.merge(dfp, sfp)
}
// TODO: Make this faster?
out := dst.asPointerTo(mi.typ).Elem()
in := src.asPointerTo(mi.typ).Elem()
if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
if emIn != nil {
mergeExtension(emOut, emIn)
}
}
if mi.unrecognized.IsValid() {
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
}
}
}
func (mi *mergeInfo) computeMergeInfo() {
mi.lock.Lock()
defer mi.lock.Unlock()
if mi.initialized != 0 {
return
}
t := mi.typ
n := t.NumField()
props := GetProperties(t)
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
mfi := mergeFieldInfo{field: toField(&f, nil)}
tf := f.Type
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
switch tf.Kind() {
case reflect.Ptr, reflect.Slice, reflect.String:
// As a special case, we assume slices and strings are pointers
// since we know that the first field in the SliceSlice or
// StringHeader is a data pointer.
mfi.isPointer = true
case reflect.Bool:
mfi.basicWidth = 1
case reflect.Int32, reflect.Uint32, reflect.Float32:
mfi.basicWidth = 4
case reflect.Int64, reflect.Uint64, reflect.Float64:
mfi.basicWidth = 8
}
}
// Unwrap tf to get at its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic("both pointer and slice for basic type in " + tf.Name())
}
switch tf.Kind() {
case reflect.Int32:
switch {
case isSlice: // E.g., []int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
/*
sfsp := src.toInt32Slice()
if *sfsp != nil {
dfsp := dst.toInt32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
*/
sfs := src.getInt32Slice()
if sfs != nil {
dfs := dst.getInt32Slice()
dfs = append(dfs, sfs...)
if dfs == nil {
dfs = []int32{}
}
dst.setInt32Slice(dfs)
}
}
case isPointer: // E.g., *int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
/*
sfpp := src.toInt32Ptr()
if *sfpp != nil {
dfpp := dst.toInt32Ptr()
if *dfpp == nil {
*dfpp = Int32(**sfpp)
} else {
**dfpp = **sfpp
}
}
*/
sfp := src.getInt32Ptr()
if sfp != nil {
dfp := dst.getInt32Ptr()
if dfp == nil {
dst.setInt32Ptr(*sfp)
} else {
*dfp = *sfp
}
}
}
default: // E.g., int32
mfi.merge = func(dst, src pointer) {
if v := *src.toInt32(); v != 0 {
*dst.toInt32() = v
}
}
}
case reflect.Int64:
switch {
case isSlice: // E.g., []int64
mfi.merge = func(dst, src pointer) {
sfsp := src.toInt64Slice()
if *sfsp != nil {
dfsp := dst.toInt64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
}
case isPointer: // E.g., *int64
mfi.merge = func(dst, src pointer) {
sfpp := src.toInt64Ptr()
if *sfpp != nil {
dfpp := dst.toInt64Ptr()
if *dfpp == nil {
*dfpp = Int64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., int64
mfi.merge = func(dst, src pointer) {
if v := *src.toInt64(); v != 0 {
*dst.toInt64() = v
}
}
}
case reflect.Uint32:
switch {
case isSlice: // E.g., []uint32
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint32Slice()
if *sfsp != nil {
dfsp := dst.toUint32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint32{}
}
}
}
case isPointer: // E.g., *uint32
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint32Ptr()
if *sfpp != nil {
dfpp := dst.toUint32Ptr()
if *dfpp == nil {
*dfpp = Uint32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint32
mfi.merge = func(dst, src pointer) {
if v := *src.toUint32(); v != 0 {
*dst.toUint32() = v
}
}
}
case reflect.Uint64:
switch {
case isSlice: // E.g., []uint64
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint64Slice()
if *sfsp != nil {
dfsp := dst.toUint64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint64{}
}
}
}
case isPointer: // E.g., *uint64
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint64Ptr()
if *sfpp != nil {
dfpp := dst.toUint64Ptr()
if *dfpp == nil {
*dfpp = Uint64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint64
mfi.merge = func(dst, src pointer) {
if v := *src.toUint64(); v != 0 {
*dst.toUint64() = v
}
}
}
case reflect.Float32:
switch {
case isSlice: // E.g., []float32
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat32Slice()
if *sfsp != nil {
dfsp := dst.toFloat32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float32{}
}
}
}
case isPointer: // E.g., *float32
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat32Ptr()
if *sfpp != nil {
dfpp := dst.toFloat32Ptr()
if *dfpp == nil {
*dfpp = Float32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float32
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat32(); v != 0 {
*dst.toFloat32() = v
}
}
}
case reflect.Float64:
switch {
case isSlice: // E.g., []float64
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat64Slice()
if *sfsp != nil {
dfsp := dst.toFloat64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float64{}
}
}
}
case isPointer: // E.g., *float64
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat64Ptr()
if *sfpp != nil {
dfpp := dst.toFloat64Ptr()
if *dfpp == nil {
*dfpp = Float64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float64
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat64(); v != 0 {
*dst.toFloat64() = v
}
}
}
case reflect.Bool:
switch {
case isSlice: // E.g., []bool
mfi.merge = func(dst, src pointer) {
sfsp := src.toBoolSlice()
if *sfsp != nil {
dfsp := dst.toBoolSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []bool{}
}
}
}
case isPointer: // E.g., *bool
mfi.merge = func(dst, src pointer) {
sfpp := src.toBoolPtr()
if *sfpp != nil {
dfpp := dst.toBoolPtr()
if *dfpp == nil {
*dfpp = Bool(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., bool
mfi.merge = func(dst, src pointer) {
if v := *src.toBool(); v {
*dst.toBool() = v
}
}
}
case reflect.String:
switch {
case isSlice: // E.g., []string
mfi.merge = func(dst, src pointer) {
sfsp := src.toStringSlice()
if *sfsp != nil {
dfsp := dst.toStringSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []string{}
}
}
}
case isPointer: // E.g., *string
mfi.merge = func(dst, src pointer) {
sfpp := src.toStringPtr()
if *sfpp != nil {
dfpp := dst.toStringPtr()
if *dfpp == nil {
*dfpp = String(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., string
mfi.merge = func(dst, src pointer) {
if v := *src.toString(); v != "" {
*dst.toString() = v
}
}
}
case reflect.Slice:
isProto3 := props.Prop[i].Proto3
switch {
case isPointer:
panic("bad pointer in byte slice case in " + tf.Name())
case tf.Elem().Kind() != reflect.Uint8:
panic("bad element kind in byte slice case in " + tf.Name())
case isSlice: // E.g., [][]byte
mfi.merge = func(dst, src pointer) {
sbsp := src.toBytesSlice()
if *sbsp != nil {
dbsp := dst.toBytesSlice()
for _, sb := range *sbsp {
if sb == nil {
*dbsp = append(*dbsp, nil)
} else {
*dbsp = append(*dbsp, append([]byte{}, sb...))
}
}
if *dbsp == nil {
*dbsp = [][]byte{}
}
}
}
default: // E.g., []byte
mfi.merge = func(dst, src pointer) {
sbp := src.toBytes()
if *sbp != nil {
dbp := dst.toBytes()
if !isProto3 || len(*sbp) > 0 {
*dbp = append([]byte{}, *sbp...)
}
}
}
}
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("message field %s without pointer", tf))
case isSlice: // E.g., []*pb.T
mi := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sps := src.getPointerSlice()
if sps != nil {
dps := dst.getPointerSlice()
for _, sp := range sps {
var dp pointer
if !sp.isNil() {
dp = valToPointer(reflect.New(tf))
mi.merge(dp, sp)
}
dps = append(dps, dp)
}
if dps == nil {
dps = []pointer{}
}
dst.setPointerSlice(dps)
}
}
default: // E.g., *pb.T
mi := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sp := src.getPointer()
if !sp.isNil() {
dp := dst.getPointer()
if dp.isNil() {
dp = valToPointer(reflect.New(tf))
dst.setPointer(dp)
}
mi.merge(dp, sp)
}
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic("bad pointer or slice in map case in " + tf.Name())
default: // E.g., map[K]V
mfi.merge = func(dst, src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
dm := dst.asPointerTo(tf).Elem()
if dm.IsNil() {
dm.Set(reflect.MakeMap(tf))
}
switch tf.Elem().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(Clone(val.Interface().(Message)))
dm.SetMapIndex(key, val)
}
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
dm.SetMapIndex(key, val)
}
default: // Basic type (e.g., string)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
dm.SetMapIndex(key, val)
}
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic("bad pointer or slice in interface case in " + tf.Name())
default: // E.g., interface{}
// TODO: Make this faster?
mfi.merge = func(dst, src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
du := dst.asPointerTo(tf).Elem()
typ := su.Elem().Type()
if du.IsNil() || du.Elem().Type() != typ {
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
}
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
dv := du.Elem().Elem().Field(0)
if dv.Kind() == reflect.Ptr && dv.IsNil() {
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
Merge(dv.Interface().(Message), sv.Interface().(Message))
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
default: // Basic type (e.g., string)
dv.Set(sv)
}
}
}
}
default:
panic(fmt.Sprintf("merger not found for type:%s", tf))
}
mi.fields = append(mi.fields, mfi)
}
expFunc := exporterFunc(t)
mi.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
mi.unrecognized = toField(&f, nil)
}
if f, ok := t.FieldByName("unknownFields"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected unknownFields to be of type []byte")
}
mi.unrecognized = toField(&f, expFunc)
}
atomic.StoreInt32(&mi.initialized, 1)
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,832 +0,0 @@
// Copyright 2010 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.
package proto
// Functions for writing the text protocol buffer format.
import (
"bufio"
"bytes"
"encoding"
"errors"
"fmt"
"io"
"log"
"math"
"reflect"
"sort"
"strings"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
)
var (
newline = []byte("\n")
spaces = []byte(" ")
endBraceNewline = []byte("}\n")
backslashN = []byte{'\\', 'n'}
backslashR = []byte{'\\', 'r'}
backslashT = []byte{'\\', 't'}
backslashDQ = []byte{'\\', '"'}
backslashBS = []byte{'\\', '\\'}
posInf = []byte("inf")
negInf = []byte("-inf")
nan = []byte("nan")
)
type writer interface {
io.Writer
WriteByte(byte) error
}
// textWriter is an io.Writer that tracks its indentation level.
type textWriter struct {
ind int
complete bool // if the current position is a complete line
compact bool // whether to write out as a one-liner
w writer
}
func (w *textWriter) WriteString(s string) (n int, err error) {
if !strings.Contains(s, "\n") {
if !w.compact && w.complete {
w.writeIndent()
}
w.complete = false
return io.WriteString(w.w, s)
}
// WriteString is typically called without newlines, so this
// codepath and its copy are rare. We copy to avoid
// duplicating all of Write's logic here.
return w.Write([]byte(s))
}
func (w *textWriter) Write(p []byte) (n int, err error) {
newlines := bytes.Count(p, newline)
if newlines == 0 {
if !w.compact && w.complete {
w.writeIndent()
}
n, err = w.w.Write(p)
w.complete = false
return n, err
}
frags := bytes.SplitN(p, newline, newlines+1)
if w.compact {
for i, frag := range frags {
if i > 0 {
if err := w.w.WriteByte(' '); err != nil {
return n, err
}
n++
}
nn, err := w.w.Write(frag)
n += nn
if err != nil {
return n, err
}
}
return n, nil
}
for i, frag := range frags {
if w.complete {
w.writeIndent()
}
nn, err := w.w.Write(frag)
n += nn
if err != nil {
return n, err
}
if i+1 < len(frags) {
if err := w.w.WriteByte('\n'); err != nil {
return n, err
}
n++
}
}
w.complete = len(frags[len(frags)-1]) == 0
return n, nil
}
func (w *textWriter) WriteByte(c byte) error {
if w.compact && c == '\n' {
c = ' '
}
if !w.compact && w.complete {
w.writeIndent()
}
err := w.w.WriteByte(c)
w.complete = c == '\n'
return err
}
func (w *textWriter) indent() { w.ind++ }
func (w *textWriter) unindent() {
if w.ind == 0 {
log.Print("proto: textWriter unindented too far")
return
}
w.ind--
}
func writeName(w *textWriter, props *Properties) error {
if _, err := w.WriteString(props.OrigName); err != nil {
return err
}
if props.Wire != "group" {
return w.WriteByte(':')
}
return nil
}
func requiresQuotes(u string) bool {
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
for _, ch := range u {
switch {
case ch == '.' || ch == '/' || ch == '_':
continue
case '0' <= ch && ch <= '9':
continue
case 'A' <= ch && ch <= 'Z':
continue
case 'a' <= ch && ch <= 'z':
continue
default:
return true
}
}
return false
}
// isAny reports whether sv is a google.protobuf.Any message
func isAny(sv reflect.Value) bool {
switch m := sv.Addr().Interface().(type) {
case interface{ XXX_WellKnownType() string }:
return m.XXX_WellKnownType() == "Any"
case protoV2.Message:
return m.ProtoReflect().Descriptor().FullName() == "google.protobuf.Any"
default:
return false
}
}
// writeProto3Any writes an expanded google.protobuf.Any message.
//
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
// required messages are not linked in).
//
// It returns (true, error) when sv was written in expanded format or an error
// was encountered.
func (tm *textMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
turl := sv.FieldByName("TypeUrl")
val := sv.FieldByName("Value")
if !turl.IsValid() || !val.IsValid() {
return true, errors.New("proto: invalid google.protobuf.Any message")
}
b, ok := val.Interface().([]byte)
if !ok {
return true, errors.New("proto: invalid google.protobuf.Any message")
}
parts := strings.Split(turl.String(), "/")
mt := MessageType(parts[len(parts)-1])
if mt == nil {
return false, nil
}
m := reflect.New(mt.Elem())
if err := Unmarshal(b, m.Interface().(Message)); err != nil {
return false, nil
}
w.Write([]byte("["))
u := turl.String()
if requiresQuotes(u) {
writeString(w, u)
} else {
w.Write([]byte(u))
}
if w.compact {
w.Write([]byte("]:<"))
} else {
w.Write([]byte("]: <\n"))
w.ind++
}
if err := tm.writeStruct(w, m.Elem()); err != nil {
return true, err
}
if w.compact {
w.Write([]byte("> "))
} else {
w.ind--
w.Write([]byte(">\n"))
}
return true, nil
}
func (tm *textMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
if tm.ExpandAny && isAny(sv) {
if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
return err
}
}
st := sv.Type()
sprops := GetProperties(st)
for i := 0; i < sv.NumField(); i++ {
fv := sv.Field(i)
props := sprops.Prop[i]
f := st.Field(i)
if strings.HasPrefix(f.Name, "XXX_") || f.PkgPath != "" {
continue
}
if fv.Kind() == reflect.Ptr && fv.IsNil() {
// Field not filled in. This could be an optional field or
// a required field that wasn't filled in. Either way, there
// isn't anything we can show for it.
continue
}
if fv.Kind() == reflect.Slice && fv.IsNil() {
// Repeated field that is empty, or a bytes field that is unused.
continue
}
if props.Repeated && fv.Kind() == reflect.Slice {
// Repeated field.
for j := 0; j < fv.Len(); j++ {
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
v := fv.Index(j)
if v.Kind() == reflect.Ptr && v.IsNil() {
// A nil message in a repeated field is not valid,
// but we can handle that more gracefully than panicking.
if _, err := w.Write([]byte("<nil>\n")); err != nil {
return err
}
continue
}
if err := tm.writeAny(w, v, props); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
continue
}
if fv.Kind() == reflect.Map {
// Map fields are rendered as a repeated struct with key/value fields.
keys := fv.MapKeys()
sort.Sort(mapKeys(keys))
for _, key := range keys {
val := fv.MapIndex(key)
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
// open struct
if err := w.WriteByte('<'); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte('\n'); err != nil {
return err
}
}
w.indent()
// key
if _, err := w.WriteString("key:"); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
// nil values aren't legal, but we can avoid panicking because of them.
if val.Kind() != reflect.Ptr || !val.IsNil() {
// value
if _, err := w.WriteString("value:"); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
// close struct
w.unindent()
if err := w.WriteByte('>'); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
continue
}
if props.Proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
// empty bytes field
continue
}
if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
// proto3 non-repeated scalar field; skip if zero value
if isProto3Zero(fv) {
continue
}
}
if fv.Kind() == reflect.Interface {
// Check if it is a oneof.
if st.Field(i).Tag.Get("protobuf_oneof") != "" {
// fv is nil, or holds a pointer to generated struct.
// That generated struct has exactly one field,
// which has a protobuf struct tag.
if fv.IsNil() {
continue
}
inner := fv.Elem().Elem() // interface -> *T -> T
tag := inner.Type().Field(0).Tag.Get("protobuf")
props = new(Properties) // Overwrite the outer props var, but not its pointee.
props.Parse(tag)
// Write the value in the oneof, not the oneof itself.
fv = inner.Field(0)
// Special case to cope with malformed messages gracefully:
// If the value in the oneof is a nil pointer, don't panic
// in writeAny.
if fv.Kind() == reflect.Ptr && fv.IsNil() {
// Use errors.New so writeAny won't render quotes.
msg := errors.New("/* nil */")
fv = reflect.ValueOf(&msg).Elem()
}
}
}
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
// Enums have a String method, so writeAny will work fine.
if err := tm.writeAny(w, fv, props); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
if fv := unknownFieldsValue(sv); !fv.IsNil() {
if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
return err
}
}
// Extensions (the XXX_extensions field).
pv := sv.Addr()
if _, err := extendable(pv.Interface()); err == nil {
if err := tm.writeExtensions(w, pv); err != nil {
return err
}
}
return nil
}
// writeAny writes an arbitrary field.
func (tm *textMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
v = reflect.Indirect(v)
// Floats have special cases.
if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
x := v.Float()
var b []byte
switch {
case math.IsInf(x, 1):
b = posInf
case math.IsInf(x, -1):
b = negInf
case math.IsNaN(x):
b = nan
}
if b != nil {
_, err := w.Write(b)
return err
}
// Other values are handled below.
}
// We don't attempt to serialise every possible value type; only those
// that can occur in protocol buffers.
switch v.Kind() {
case reflect.Slice:
// Should only be a []byte; repeated fields are handled in writeStruct.
if err := writeString(w, string(v.Bytes())); err != nil {
return err
}
case reflect.String:
if err := writeString(w, v.String()); err != nil {
return err
}
case reflect.Struct:
// Required/optional group/message.
var bra, ket byte = '<', '>'
if props != nil && props.Wire == "group" {
bra, ket = '{', '}'
}
if err := w.WriteByte(bra); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte('\n'); err != nil {
return err
}
}
w.indent()
if v.CanAddr() {
// Calling v.Interface on a struct causes the reflect package to
// copy the entire struct. This is racy with the new Marshaler
// since we atomically update the XXX_sizecache.
//
// Thus, we retrieve a pointer to the struct if possible to avoid
// a race since v.Interface on the pointer doesn't copy the struct.
//
// If v is not addressable, then we are not worried about a race
// since it implies that the binary Marshaler cannot possibly be
// mutating this value.
v = v.Addr()
}
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
return err
}
if _, err = w.Write(text); err != nil {
return err
}
} else {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if err := tm.writeStruct(w, v); err != nil {
return err
}
}
w.unindent()
if err := w.WriteByte(ket); err != nil {
return err
}
default:
_, err := fmt.Fprint(w, v.Interface())
return err
}
return nil
}
// equivalent to C's isprint.
func isprint(c byte) bool {
return c >= 0x20 && c < 0x7f
}
// writeString writes a string in the protocol buffer text format.
// It is similar to strconv.Quote except we don't use Go escape sequences,
// we treat the string as a byte sequence, and we use octal escapes.
// These differences are to maintain interoperability with the other
// languages' implementations of the text format.
func writeString(w *textWriter, s string) error {
// use WriteByte here to get any needed indent
if err := w.WriteByte('"'); err != nil {
return err
}
// Loop over the bytes, not the runes.
for i := 0; i < len(s); i++ {
var err error
// Divergence from C++: we don't escape apostrophes.
// There's no need to escape them, and the C++ parser
// copes with a naked apostrophe.
switch c := s[i]; c {
case '\n':
_, err = w.w.Write(backslashN)
case '\r':
_, err = w.w.Write(backslashR)
case '\t':
_, err = w.w.Write(backslashT)
case '"':
_, err = w.w.Write(backslashDQ)
case '\\':
_, err = w.w.Write(backslashBS)
default:
if isprint(c) {
err = w.w.WriteByte(c)
} else {
_, err = fmt.Fprintf(w.w, "\\%03o", c)
}
}
if err != nil {
return err
}
}
return w.WriteByte('"')
}
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
if !w.compact {
if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
return err
}
}
b := NewBuffer(data)
for b.index < len(b.buf) {
x, err := b.DecodeVarint()
if err != nil {
_, err := fmt.Fprintf(w, "/* %v */\n", err)
return err
}
wire, tag := x&7, x>>3
if wire == WireEndGroup {
w.unindent()
if _, err := w.Write(endBraceNewline); err != nil {
return err
}
continue
}
if _, err := fmt.Fprint(w, tag); err != nil {
return err
}
if wire != WireStartGroup {
if err := w.WriteByte(':'); err != nil {
return err
}
}
if !w.compact || wire == WireStartGroup {
if err := w.WriteByte(' '); err != nil {
return err
}
}
switch wire {
case WireBytes:
buf, e := b.DecodeRawBytes(false)
if e == nil {
_, err = fmt.Fprintf(w, "%q", buf)
} else {
_, err = fmt.Fprintf(w, "/* %v */", e)
}
case WireFixed32:
x, err = b.DecodeFixed32()
err = writeUnknownInt(w, x, err)
case WireFixed64:
x, err = b.DecodeFixed64()
err = writeUnknownInt(w, x, err)
case WireStartGroup:
err = w.WriteByte('{')
w.indent()
case WireVarint:
x, err = b.DecodeVarint()
err = writeUnknownInt(w, x, err)
default:
_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
}
if err != nil {
return err
}
if err = w.WriteByte('\n'); err != nil {
return err
}
}
return nil
}
func writeUnknownInt(w *textWriter, x uint64, err error) error {
if err == nil {
_, err = fmt.Fprint(w, x)
} else {
_, err = fmt.Fprintf(w, "/* %v */", err)
}
return err
}
type fieldNumSlice []protoreflect.FieldNumber
func (s fieldNumSlice) Len() int { return len(s) }
func (s fieldNumSlice) Less(i, j int) bool { return s[i] < s[j] }
func (s fieldNumSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// writeExtensions writes all the extensions in pv.
// pv is assumed to be a pointer to a protocol message struct that is extendable.
func (tm *textMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
emap := RegisteredExtensions(pv.Interface().(Message))
ep, _ := extendable(pv.Interface())
// Order the extensions by ID.
// This isn't strictly necessary, but it will give us
// canonical output, which will also make testing easier.
if ep == nil {
return nil
}
ids := make([]protoreflect.FieldNumber, 0, ep.Len())
ep.Range(func(id protoreflect.FieldNumber, _ Extension) bool {
ids = append(ids, id)
return true
})
sort.Sort(fieldNumSlice(ids))
for _, extNum := range ids {
var desc *ExtensionDesc
if emap != nil {
desc = emap[int32(extNum)]
}
if desc == nil {
continue
}
pb, err := GetExtension(pv.Interface().(Message), desc)
if err != nil {
return fmt.Errorf("failed getting extension: %v", err)
}
name := desc.Name
if strings.HasSuffix(name, ".message_set_extension") && isMessageSet(pv.Type().Elem()) {
name = strings.TrimSuffix(name, ".message_set_extension")
}
// Repeated extensions will appear as a slice.
if !isRepeatedExtension(desc) {
if err := tm.writeExtension(w, name, pb); err != nil {
return err
}
} else {
v := reflect.ValueOf(pb)
for i := 0; i < v.Len(); i++ {
if err := tm.writeExtension(w, name, v.Index(i).Interface()); err != nil {
return err
}
}
}
}
return nil
}
func (tm *textMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
return nil
}
func (w *textWriter) writeIndent() {
if !w.complete {
return
}
remain := w.ind * 2
for remain > 0 {
n := remain
if n > len(spaces) {
n = len(spaces)
}
w.w.Write(spaces[:n])
remain -= n
}
w.complete = false
}
// textMarshaler is a configurable text format marshaler.
type textMarshaler struct {
Compact bool // use compact text format (one line).
ExpandAny bool // expand google.protobuf.Any messages of known types
}
// Marshal writes a given protocol buffer in text format.
// The only errors returned are from w.
func (tm *textMarshaler) Marshal(w io.Writer, pb Message) error {
val := reflect.ValueOf(pb)
if pb == nil || val.IsNil() {
w.Write([]byte("<nil>"))
return nil
}
var bw *bufio.Writer
ww, ok := w.(writer)
if !ok {
bw = bufio.NewWriter(w)
ww = bw
}
aw := &textWriter{
w: ww,
complete: true,
compact: tm.Compact,
}
if etm, ok := pb.(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
return err
}
if _, err = aw.Write(text); err != nil {
return err
}
if bw != nil {
return bw.Flush()
}
return nil
}
// Dereference the received pointer so we don't have outer < and >.
v := reflect.Indirect(val)
if err := tm.writeStruct(aw, v); err != nil {
return err
}
if bw != nil {
return bw.Flush()
}
return nil
}
// Text is the same as Marshal, but returns the string directly.
func (tm *textMarshaler) Text(pb Message) string {
var buf bytes.Buffer
tm.Marshal(&buf, pb)
return buf.String()
}
var (
defaultTextMarshaler = textMarshaler{}
compactTextMarshaler = textMarshaler{Compact: true}
)
// TODO: consider removing some of the Marshal functions below.
// MarshalText writes a given protocol buffer in text format.
// The only errors returned are from w.
func MarshalText(w io.Writer, pb Message) error {
if marshalTextAlt != nil {
return marshalTextAlt(w, pb)
}
return defaultTextMarshaler.Marshal(w, pb)
}
// MarshalTextString is the same as MarshalText, but returns the string directly.
func MarshalTextString(pb Message) string {
if marshalTextStringAlt != nil {
return marshalTextStringAlt(pb)
}
return defaultTextMarshaler.Text(pb)
}
// CompactText writes a given protocol buffer in compact text format (one line).
func CompactText(w io.Writer, pb Message) error {
if compactTextAlt != nil {
return compactTextAlt(w, pb)
}
return compactTextMarshaler.Marshal(w, pb)
}
// CompactTextString is the same as CompactText, but returns the string directly.
func CompactTextString(pb Message) string {
if compactTextStringAlt != nil {
return compactTextStringAlt(pb)
}
return compactTextMarshaler.Text(pb)
}

799
proto/text_decode.go Normal file
Просмотреть файл

@ -0,0 +1,799 @@
// Copyright 2010 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.
package proto
import (
"encoding"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"unicode/utf8"
"google.golang.org/protobuf/encoding/prototext"
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
const wrapTextUnmarshalV2 = false
// ParseError is returned by UnmarshalText.
type ParseError struct {
Message string
// Deprecated: Do not use.
Line, Offset int
}
func (e *ParseError) Error() string {
if wrapTextUnmarshalV2 {
return e.Message
}
if e.Line == 1 {
return fmt.Sprintf("line 1.%d: %v", e.Offset, e.Message)
}
return fmt.Sprintf("line %d: %v", e.Line, e.Message)
}
// UnmarshalText parses a proto text formatted string into m.
func UnmarshalText(s string, m Message) error {
if u, ok := m.(encoding.TextUnmarshaler); ok {
return u.UnmarshalText([]byte(s))
}
m.Reset()
mi := protoimpl.X.ProtoMessageV2Of(m)
if wrapTextUnmarshalV2 {
err := prototext.UnmarshalOptions{
AllowPartial: true,
}.Unmarshal([]byte(s), mi)
if err != nil {
return &ParseError{Message: err.Error()}
}
return checkRequiredNotSet(mi)
} else {
if err := newTextParser(s).unmarshalMessage(mi.ProtoReflect(), ""); err != nil {
return err
}
return checkRequiredNotSet(mi)
}
}
type textParser struct {
s string // remaining input
done bool // whether the parsing is finished (success or error)
backed bool // whether back() was called
offset, line int
cur token
}
type token struct {
value string
err *ParseError
line int // line number
offset int // byte number from start of input, not start of line
unquoted string // the unquoted version of value, if it was a quoted string
}
func newTextParser(s string) *textParser {
p := new(textParser)
p.s = s
p.line = 1
p.cur.line = 1
return p
}
func (p *textParser) unmarshalMessage(m protoreflect.Message, terminator string) (err error) {
md := m.Descriptor()
fds := md.Fields()
// A struct is a sequence of "name: value", terminated by one of
// '>' or '}', or the end of the input. A name may also be
// "[extension]" or "[type/url]".
//
// The whole struct can also be an expanded Any message, like:
// [type/url] < ... struct contents ... >
seen := make(map[protoreflect.FieldNumber]bool)
for {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == terminator {
break
}
if tok.value == "[" {
if err := p.unmarshalExtensionOrAny(m, seen); err != nil {
return err
}
continue
}
// This is a normal, non-extension field.
name := protoreflect.Name(tok.value)
fd := fds.ByName(name)
switch {
case fd == nil:
gd := fds.ByName(protoreflect.Name(strings.ToLower(string(name))))
if gd != nil && gd.Kind() == protoreflect.GroupKind && gd.Message().Name() == name {
fd = gd
}
case fd.Kind() == protoreflect.GroupKind && fd.Message().Name() != name:
fd = nil
case fd.IsWeak() && fd.Message().IsPlaceholder():
fd = nil
}
if fd == nil {
typeName := string(md.FullName())
if m, ok := m.Interface().(Message); ok {
t := reflect.TypeOf(m)
if t.Kind() == reflect.Ptr {
typeName = t.Elem().String()
}
}
return p.errorf("unknown field name %q in %v", name, typeName)
}
if od := fd.ContainingOneof(); od != nil && m.WhichOneof(od) != nil {
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, od.Name())
}
if fd.Cardinality() != protoreflect.Repeated && seen[fd.Number()] {
return p.errorf("non-repeated field %q was repeated", fd.Name())
}
seen[fd.Number()] = true
// Consume any colon.
if err := p.checkForColon(fd); err != nil {
return err
}
// Parse into the field.
v := m.Get(fd)
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
v = m.Mutable(fd)
}
if v, err = p.unmarshalValue(v, fd); err != nil {
return err
}
m.Set(fd, v)
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
}
return nil
}
func (p *textParser) unmarshalExtensionOrAny(m protoreflect.Message, seen map[protoreflect.FieldNumber]bool) error {
name, err := p.consumeExtensionOrAnyName()
if err != nil {
return err
}
// If it contains a slash, it's an Any type URL.
if slashIdx := strings.LastIndex(name, "/"); slashIdx >= 0 {
tok := p.next()
if tok.err != nil {
return tok.err
}
// consume an optional colon
if tok.value == ":" {
tok = p.next()
if tok.err != nil {
return tok.err
}
}
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
mt, err := protoregistry.GlobalTypes.FindMessageByURL(name)
if err != nil {
return p.errorf("unrecognized message %q in google.protobuf.Any", name[slashIdx+len("/"):])
}
m2 := mt.New()
if err := p.unmarshalMessage(m2, terminator); err != nil {
return err
}
b, err := protoV2.Marshal(m2.Interface())
if err != nil {
return p.errorf("failed to marshal message of type %q: %v", name[slashIdx+len("/"):], err)
}
urlFD := m.Descriptor().Fields().ByName("type_url")
valFD := m.Descriptor().Fields().ByName("value")
if seen[urlFD.Number()] {
return p.errorf("Any message unpacked multiple times, or %q already set", urlFD.Name())
}
if seen[valFD.Number()] {
return p.errorf("Any message unpacked multiple times, or %q already set", valFD.Name())
}
m.Set(urlFD, protoreflect.ValueOfString(name))
m.Set(valFD, protoreflect.ValueOfBytes(b))
seen[urlFD.Number()] = true
seen[valFD.Number()] = true
return nil
}
xname := protoreflect.FullName(name)
xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname)
if xt == nil && isMessageSet(m.Descriptor()) {
xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension"))
}
if xt == nil {
return p.errorf("unrecognized extension %q", name)
}
fd := xt.TypeDescriptor()
if err := p.checkForColon(fd); err != nil {
return err
}
v := m.Get(fd)
if !m.Has(fd) && (fd.IsList() || fd.IsMap() || fd.Message() != nil) {
v = m.Mutable(fd)
}
v, err = p.unmarshalValue(v, fd)
if err != nil {
return err
}
m.Set(fd, v)
return p.consumeOptionalSeparator()
}
func (p *textParser) unmarshalValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
tok := p.next()
if tok.err != nil {
return v, tok.err
}
if tok.value == "" {
return v, p.errorf("unexpected EOF")
}
switch {
case fd.IsList():
lv := v.List()
var err error
if tok.value == "[" {
// Repeated field with list notation, like [1,2,3].
for {
vv := lv.NewElement()
vv, err = p.unmarshalSingularValue(vv, fd)
if err != nil {
return v, err
}
lv.Append(vv)
tok := p.next()
if tok.err != nil {
return v, tok.err
}
if tok.value == "]" {
break
}
if tok.value != "," {
return v, p.errorf("Expected ']' or ',' found %q", tok.value)
}
}
return v, nil
}
// One value of the repeated field.
p.back()
vv := lv.NewElement()
vv, err = p.unmarshalSingularValue(vv, fd)
if err != nil {
return v, err
}
lv.Append(vv)
return v, nil
case fd.IsMap():
// The map entry should be this sequence of tokens:
// < key : KEY value : VALUE >
// However, implementations may omit key or value, and technically
// we should support them in any order.
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return v, p.errorf("expected '{' or '<', found %q", tok.value)
}
keyFD := fd.MapKey()
valFD := fd.MapValue()
mv := v.Map()
kv := keyFD.Default()
vv := mv.NewValue()
for {
tok := p.next()
if tok.err != nil {
return v, tok.err
}
if tok.value == terminator {
break
}
var err error
switch tok.value {
case "key":
if err := p.consumeToken(":"); err != nil {
return v, err
}
if kv, err = p.unmarshalSingularValue(kv, keyFD); err != nil {
return v, err
}
if err := p.consumeOptionalSeparator(); err != nil {
return v, err
}
case "value":
if err := p.checkForColon(valFD); err != nil {
return v, err
}
if vv, err = p.unmarshalSingularValue(vv, valFD); err != nil {
return v, err
}
if err := p.consumeOptionalSeparator(); err != nil {
return v, err
}
default:
p.back()
return v, p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
}
}
mv.Set(kv.MapKey(), vv)
return v, nil
default:
p.back()
return p.unmarshalSingularValue(v, fd)
}
}
func (p *textParser) unmarshalSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
tok := p.next()
if tok.err != nil {
return v, tok.err
}
if tok.value == "" {
return v, p.errorf("unexpected EOF")
}
switch fd.Kind() {
case protoreflect.BoolKind:
switch tok.value {
case "true", "1", "t", "True":
return protoreflect.ValueOfBool(true), nil
case "false", "0", "f", "False":
return protoreflect.ValueOfBool(false), nil
}
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
return protoreflect.ValueOfInt32(int32(x)), nil
}
// The C++ parser accepts large positive hex numbers that uses
// two's complement arithmetic to represent negative numbers.
// This feature is here for backwards compatibility with C++.
if strings.HasPrefix(tok.value, "0x") {
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
return protoreflect.ValueOfInt32(int32(-(int64(^x) + 1))), nil
}
}
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
return protoreflect.ValueOfInt64(int64(x)), nil
}
// The C++ parser accepts large positive hex numbers that uses
// two's complement arithmetic to represent negative numbers.
// This feature is here for backwards compatibility with C++.
if strings.HasPrefix(tok.value, "0x") {
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
return protoreflect.ValueOfInt64(int64(-(int64(^x) + 1))), nil
}
}
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
return protoreflect.ValueOfUint32(uint32(x)), nil
}
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
return protoreflect.ValueOfUint64(uint64(x)), nil
}
case protoreflect.FloatKind:
// Ignore 'f' for compatibility with output generated by C++,
// but don't remove 'f' when the value is "-inf" or "inf".
v := tok.value
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
v = v[:len(v)-len("f")]
}
if x, err := strconv.ParseFloat(v, 32); err == nil {
return protoreflect.ValueOfFloat32(float32(x)), nil
}
case protoreflect.DoubleKind:
// Ignore 'f' for compatibility with output generated by C++,
// but don't remove 'f' when the value is "-inf" or "inf".
v := tok.value
if strings.HasSuffix(v, "f") && v != "-inf" && v != "inf" {
v = v[:len(v)-len("f")]
}
if x, err := strconv.ParseFloat(v, 64); err == nil {
return protoreflect.ValueOfFloat64(float64(x)), nil
}
case protoreflect.StringKind:
if isQuote(tok.value[0]) {
return protoreflect.ValueOfString(tok.unquoted), nil
}
case protoreflect.BytesKind:
if isQuote(tok.value[0]) {
return protoreflect.ValueOfBytes([]byte(tok.unquoted)), nil
}
case protoreflect.EnumKind:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(x)), nil
}
vd := fd.Enum().Values().ByName(protoreflect.Name(tok.value))
if vd != nil {
return protoreflect.ValueOfEnum(vd.Number()), nil
}
case protoreflect.MessageKind, protoreflect.GroupKind:
var terminator string
switch tok.value {
case "{":
terminator = "}"
case "<":
terminator = ">"
default:
return v, p.errorf("expected '{' or '<', found %q", tok.value)
}
err := p.unmarshalMessage(v.Message(), terminator)
return v, err
default:
panic(fmt.Sprintf("invalid kind %v", fd.Kind()))
}
return v, p.errorf("invalid %v: %v", fd.Kind(), tok.value)
}
// Consume a ':' from the input stream (if the next token is a colon),
// returning an error if a colon is needed but not present.
func (p *textParser) checkForColon(fd protoreflect.FieldDescriptor) *ParseError {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ":" {
if fd.Message() == nil {
return p.errorf("expected ':', found %q", tok.value)
}
p.back()
}
return nil
}
// consumeExtensionOrAnyName consumes an extension name or an Any type URL and
// the following ']'. It returns the name or URL consumed.
func (p *textParser) consumeExtensionOrAnyName() (string, error) {
tok := p.next()
if tok.err != nil {
return "", tok.err
}
// If extension name or type url is quoted, it's a single token.
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
if err != nil {
return "", err
}
return name, p.consumeToken("]")
}
// Consume everything up to "]"
var parts []string
for tok.value != "]" {
parts = append(parts, tok.value)
tok = p.next()
if tok.err != nil {
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
}
if p.done && tok.value != "]" {
return "", p.errorf("unclosed type_url or extension name")
}
}
return strings.Join(parts, ""), nil
}
// consumeOptionalSeparator consumes an optional semicolon or comma.
// It is used in unmarshalMessage to provide backward compatibility.
func (p *textParser) consumeOptionalSeparator() error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ";" && tok.value != "," {
p.back()
}
return nil
}
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
p.cur.err = pe
p.done = true
return pe
}
func (p *textParser) skipWhitespace() {
i := 0
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
if p.s[i] == '#' {
// comment; skip to end of line or input
for i < len(p.s) && p.s[i] != '\n' {
i++
}
if i == len(p.s) {
break
}
}
if p.s[i] == '\n' {
p.line++
}
i++
}
p.offset += i
p.s = p.s[i:len(p.s)]
if len(p.s) == 0 {
p.done = true
}
}
func (p *textParser) advance() {
// Skip whitespace
p.skipWhitespace()
if p.done {
return
}
// Start of non-whitespace
p.cur.err = nil
p.cur.offset, p.cur.line = p.offset, p.line
p.cur.unquoted = ""
switch p.s[0] {
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
// Single symbol
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
case '"', '\'':
// Quoted string
i := 1
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
if p.s[i] == '\\' && i+1 < len(p.s) {
// skip escaped char
i++
}
i++
}
if i >= len(p.s) || p.s[i] != p.s[0] {
p.errorf("unmatched quote")
return
}
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
if err != nil {
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
return
}
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
p.cur.unquoted = unq
default:
i := 0
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
i++
}
if i == 0 {
p.errorf("unexpected byte %#x", p.s[0])
return
}
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
}
p.offset += len(p.cur.value)
}
// Back off the parser by one token. Can only be done between calls to next().
// It makes the next advance() a no-op.
func (p *textParser) back() { p.backed = true }
// Advances the parser and returns the new current token.
func (p *textParser) next() *token {
if p.backed || p.done {
p.backed = false
return &p.cur
}
p.advance()
if p.done {
p.cur.value = ""
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
// Look for multiple quoted strings separated by whitespace,
// and concatenate them.
cat := p.cur
for {
p.skipWhitespace()
if p.done || !isQuote(p.s[0]) {
break
}
p.advance()
if p.cur.err != nil {
return &p.cur
}
cat.value += " " + p.cur.value
cat.unquoted += p.cur.unquoted
}
p.done = false // parser may have seen EOF, but we want to return cat
p.cur = cat
}
return &p.cur
}
func (p *textParser) consumeToken(s string) error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != s {
p.back()
return p.errorf("expected %q, found %q", s, tok.value)
}
return nil
}
var errBadUTF8 = errors.New("proto: bad UTF-8")
func unquoteC(s string, quote rune) (string, error) {
// This is based on C++'s tokenizer.cc.
// Despite its name, this is *not* parsing C syntax.
// For instance, "\0" is an invalid quoted string.
// Avoid allocation in trivial cases.
simple := true
for _, r := range s {
if r == '\\' || r == quote {
simple = false
break
}
}
if simple {
return s, nil
}
buf := make([]byte, 0, 3*len(s)/2)
for len(s) > 0 {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", errBadUTF8
}
s = s[n:]
if r != '\\' {
if r < utf8.RuneSelf {
buf = append(buf, byte(r))
} else {
buf = append(buf, string(r)...)
}
continue
}
ch, tail, err := unescape(s)
if err != nil {
return "", err
}
buf = append(buf, ch...)
s = tail
}
return string(buf), nil
}
func unescape(s string) (ch string, tail string, err error) {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", "", errBadUTF8
}
s = s[n:]
switch r {
case 'a':
return "\a", s, nil
case 'b':
return "\b", s, nil
case 'f':
return "\f", s, nil
case 'n':
return "\n", s, nil
case 'r':
return "\r", s, nil
case 't':
return "\t", s, nil
case 'v':
return "\v", s, nil
case '?':
return "?", s, nil // trigraph workaround
case '\'', '"', '\\':
return string(r), s, nil
case '0', '1', '2', '3', '4', '5', '6', '7':
if len(s) < 2 {
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
}
ss := string(r) + s[:2]
s = s[2:]
i, err := strconv.ParseUint(ss, 8, 8)
if err != nil {
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
}
return string([]byte{byte(i)}), s, nil
case 'x', 'X', 'u', 'U':
var n int
switch r {
case 'x', 'X':
n = 2
case 'u':
n = 4
case 'U':
n = 8
}
if len(s) < n {
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
}
ss := s[:n]
s = s[n:]
i, err := strconv.ParseUint(ss, 16, 64)
if err != nil {
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
}
if r == 'x' || r == 'X' {
return string([]byte{byte(i)}), s, nil
}
if i > utf8.MaxRune {
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
}
return string(i), s, nil
}
return "", "", fmt.Errorf(`unknown escape \%c`, r)
}
func isIdentOrNumberChar(c byte) bool {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
return true
case '0' <= c && c <= '9':
return true
}
switch c {
case '-', '+', '.', '_':
return true
}
return false
}
func isWhitespace(c byte) bool {
switch c {
case ' ', '\t', '\n', '\r':
return true
}
return false
}
func isQuote(c byte) bool {
switch c {
case '"', '\'':
return true
}
return false
}

561
proto/text_encode.go Normal file
Просмотреть файл

@ -0,0 +1,561 @@
// Copyright 2010 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.
package proto
import (
"bytes"
"encoding"
"fmt"
"io"
"math"
"sort"
"strings"
"github.com/golang/protobuf/internal/wire"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
)
const wrapTextMarshalV2 = false
// TextMarshaler is a configurable text format marshaler.
type TextMarshaler struct {
Compact bool // use compact text format (one line)
ExpandAny bool // expand google.protobuf.Any messages of known types
}
// Marshal writes the proto text format of m to w.
func (tm *TextMarshaler) Marshal(w io.Writer, m Message) error {
b, err := tm.marshal(m)
if len(b) > 0 {
if _, err := w.Write(b); err != nil {
return err
}
}
return err
}
// Text returns a proto text formatted string of m.
func (tm *TextMarshaler) Text(m Message) string {
b, _ := tm.marshal(m)
return string(b)
}
func (tm *TextMarshaler) marshal(m Message) ([]byte, error) {
mr := protoimpl.X.MessageOf(m)
if mr == nil || !mr.IsValid() {
return []byte("<nil>"), nil
}
if wrapTextMarshalV2 {
if m, ok := m.(encoding.TextMarshaler); ok {
return m.MarshalText()
}
opts := prototext.MarshalOptions{
AllowPartial: true,
EmitUnknown: true,
}
if !tm.Compact {
opts.Indent = " "
}
if !tm.ExpandAny {
opts.Resolver = (*protoregistry.Types)(nil)
}
return opts.Marshal(mr.Interface())
} else {
w := &textWriter{
compact: tm.Compact,
expandAny: tm.ExpandAny,
complete: true,
}
if m, ok := m.(encoding.TextMarshaler); ok {
b, err := m.MarshalText()
if err != nil {
return nil, err
}
w.Write(b)
return w.buf, nil
}
err := w.writeMessage(mr)
return w.buf, err
}
}
var (
defaultTextMarshaler = TextMarshaler{}
compactTextMarshaler = TextMarshaler{Compact: true}
)
// MarshalText writes the proto text format of m to w.
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
// MarshalTextString returns a proto text formatted string of m.
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
// CompactText writes the compact proto text format of m to w.
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
// CompactTextString returns a compact proto text formatted string of m.
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
var (
newline = []byte("\n")
endBraceNewline = []byte("}\n")
posInf = []byte("inf")
negInf = []byte("-inf")
nan = []byte("nan")
)
// textWriter is an io.Writer that tracks its indentation level.
type textWriter struct {
compact bool // same as TextMarshaler.Compact
expandAny bool // same as TextMarshaler.ExpandAny
complete bool // whether the current position is a complete line
indent int // indentation level; never negative
buf []byte
}
func (w *textWriter) Write(p []byte) (n int, _ error) {
newlines := bytes.Count(p, newline)
if newlines == 0 {
if !w.compact && w.complete {
w.writeIndent()
}
w.buf = append(w.buf, p...)
w.complete = false
return len(p), nil
}
frags := bytes.SplitN(p, newline, newlines+1)
if w.compact {
for i, frag := range frags {
if i > 0 {
w.buf = append(w.buf, ' ')
n++
}
w.buf = append(w.buf, frag...)
n += len(frag)
}
return n, nil
}
for i, frag := range frags {
if w.complete {
w.writeIndent()
}
w.buf = append(w.buf, frag...)
n += len(frag)
if i+1 < len(frags) {
w.buf = append(w.buf, '\n')
n++
}
}
w.complete = len(frags[len(frags)-1]) == 0
return n, nil
}
func (w *textWriter) WriteByte(c byte) error {
if w.compact && c == '\n' {
c = ' '
}
if !w.compact && w.complete {
w.writeIndent()
}
w.buf = append(w.buf, c)
w.complete = c == '\n'
return nil
}
func (w *textWriter) writeName(fd protoreflect.FieldDescriptor) {
if !w.compact && w.complete {
w.writeIndent()
}
w.complete = false
if fd.Kind() != protoreflect.GroupKind {
w.buf = append(w.buf, fd.Name()...)
w.WriteByte(':')
} else {
// Use message type name for group field name.
w.buf = append(w.buf, fd.Message().Name()...)
}
if !w.compact {
w.WriteByte(' ')
}
}
func requiresQuotes(u string) bool {
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
for _, ch := range u {
switch {
case ch == '.' || ch == '/' || ch == '_':
continue
case '0' <= ch && ch <= '9':
continue
case 'A' <= ch && ch <= 'Z':
continue
case 'a' <= ch && ch <= 'z':
continue
default:
return true
}
}
return false
}
// writeProto3Any writes an expanded google.protobuf.Any message.
//
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
// required messages are not linked in).
//
// It returns (true, error) when sv was written in expanded format or an error
// was encountered.
func (w *textWriter) writeProto3Any(m protoreflect.Message) (bool, error) {
md := m.Descriptor()
fdURL := md.Fields().ByName("type_url")
fdVal := md.Fields().ByName("value")
url := m.Get(fdURL).String()
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
if err != nil {
return false, nil
}
b := m.Get(fdVal).Bytes()
m2 := mt.New()
if err := proto.Unmarshal(b, m2.Interface()); err != nil {
return false, nil
}
w.Write([]byte("["))
if requiresQuotes(url) {
w.writeQuotedString(url)
} else {
w.Write([]byte(url))
}
if w.compact {
w.Write([]byte("]:<"))
} else {
w.Write([]byte("]: <\n"))
w.indent++
}
if err := w.writeMessage(m2); err != nil {
return true, err
}
if w.compact {
w.Write([]byte("> "))
} else {
w.indent--
w.Write([]byte(">\n"))
}
return true, nil
}
func (w *textWriter) writeMessage(m protoreflect.Message) error {
md := m.Descriptor()
if w.expandAny && md.FullName() == "google.protobuf.Any" {
if canExpand, err := w.writeProto3Any(m); canExpand {
return err
}
}
fds := md.Fields()
for i := 0; i < fds.Len(); {
fd := fds.Get(i)
if od := fd.ContainingOneof(); od != nil {
fd = m.WhichOneof(od)
i += od.Fields().Len()
} else {
i++
}
if fd == nil || !m.Has(fd) {
continue
}
switch {
case fd.IsList():
lv := m.Get(fd).List()
for j := 0; j < lv.Len(); j++ {
w.writeName(fd)
v := lv.Get(j)
if err := w.writeSingularValue(v, fd); err != nil {
return err
}
w.WriteByte('\n')
}
case fd.IsMap():
kfd := fd.MapKey()
vfd := fd.MapValue()
mv := m.Get(fd).Map()
type entry struct{ key, val protoreflect.Value }
var entries []entry
mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
entries = append(entries, entry{k.Value(), v})
return true
})
sort.Slice(entries, func(i, j int) bool {
switch kfd.Kind() {
case protoreflect.BoolKind:
return !entries[i].key.Bool() && entries[j].key.Bool()
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return entries[i].key.Int() < entries[j].key.Int()
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return entries[i].key.Uint() < entries[j].key.Uint()
case protoreflect.StringKind:
return entries[i].key.String() < entries[j].key.String()
default:
panic("invalid kind")
}
})
for _, entry := range entries {
w.writeName(fd)
w.WriteByte('<')
if !w.compact {
w.WriteByte('\n')
}
w.indent++
w.writeName(kfd)
if err := w.writeSingularValue(entry.key, kfd); err != nil {
return err
}
w.WriteByte('\n')
w.writeName(vfd)
if err := w.writeSingularValue(entry.val, vfd); err != nil {
return err
}
w.WriteByte('\n')
w.indent--
w.WriteByte('>')
w.WriteByte('\n')
}
default:
w.writeName(fd)
if err := w.writeSingularValue(m.Get(fd), fd); err != nil {
return err
}
w.WriteByte('\n')
}
}
if b := m.GetUnknown(); len(b) > 0 {
w.writeUnknownFields(b)
}
return w.writeExtensions(m)
}
func (w *textWriter) writeSingularValue(v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
switch fd.Kind() {
case protoreflect.FloatKind, protoreflect.DoubleKind:
switch vf := v.Float(); {
case math.IsInf(vf, +1):
w.Write(posInf)
case math.IsInf(vf, -1):
w.Write(negInf)
case math.IsNaN(vf):
w.Write(nan)
default:
fmt.Fprint(w, v.Interface())
}
case protoreflect.StringKind:
// NOTE: This does not validate UTF-8 for historical reasons.
w.writeQuotedString(string(v.String()))
case protoreflect.BytesKind:
w.writeQuotedString(string(v.Bytes()))
case protoreflect.MessageKind, protoreflect.GroupKind:
var bra, ket byte = '<', '>'
if fd.Kind() == protoreflect.GroupKind {
bra, ket = '{', '}'
}
w.WriteByte(bra)
if !w.compact {
w.WriteByte('\n')
}
w.indent++
m := v.Message()
if m2, ok := m.Interface().(encoding.TextMarshaler); ok {
b, err := m2.MarshalText()
if err != nil {
return err
}
w.Write(b)
} else {
w.writeMessage(m)
}
w.indent--
w.WriteByte(ket)
case protoreflect.EnumKind:
if ev := fd.Enum().Values().ByNumber(v.Enum()); ev != nil {
fmt.Fprint(w, ev.Name())
} else {
fmt.Fprint(w, v.Enum())
}
default:
fmt.Fprint(w, v.Interface())
}
return nil
}
// writeQuotedString writes a quoted string in the protocol buffer text format.
func (w *textWriter) writeQuotedString(s string) {
w.WriteByte('"')
for i := 0; i < len(s); i++ {
switch c := s[i]; c {
case '\n':
w.buf = append(w.buf, `\n`...)
case '\r':
w.buf = append(w.buf, `\r`...)
case '\t':
w.buf = append(w.buf, `\t`...)
case '"':
w.buf = append(w.buf, `\"`...)
case '\\':
w.buf = append(w.buf, `\\`...)
default:
if isPrint := c >= 0x20 && c < 0x7f; isPrint {
w.buf = append(w.buf, c)
} else {
w.buf = append(w.buf, fmt.Sprintf(`\%03o`, c)...)
}
}
}
w.WriteByte('"')
}
func (w *textWriter) writeUnknownFields(b []byte) {
if !w.compact {
fmt.Fprintf(w, "/* %d unknown bytes */\n", len(b))
}
for len(b) > 0 {
num, wtyp, n := wire.ConsumeTag(b)
if n < 0 {
return
}
b = b[n:]
if wtyp == wire.EndGroupType {
w.indent--
w.Write(endBraceNewline)
continue
}
fmt.Fprint(w, num)
if wtyp != wire.StartGroupType {
w.WriteByte(':')
}
if !w.compact || wtyp == wire.StartGroupType {
w.WriteByte(' ')
}
switch wtyp {
case wire.VarintType:
v, n := wire.ConsumeVarint(b)
if n < 0 {
return
}
b = b[n:]
fmt.Fprint(w, v)
case wire.Fixed32Type:
v, n := wire.ConsumeFixed32(b)
if n < 0 {
return
}
b = b[n:]
fmt.Fprint(w, v)
case wire.Fixed64Type:
v, n := wire.ConsumeFixed64(b)
if n < 0 {
return
}
b = b[n:]
fmt.Fprint(w, v)
case wire.BytesType:
v, n := wire.ConsumeBytes(b)
if n < 0 {
return
}
b = b[n:]
fmt.Fprintf(w, "%q", v)
case wire.StartGroupType:
w.WriteByte('{')
w.indent++
default:
fmt.Fprintf(w, "/* unknown wire type %d */", wtyp)
}
w.WriteByte('\n')
}
}
// writeExtensions writes all the extensions in m.
func (w *textWriter) writeExtensions(m protoreflect.Message) error {
md := m.Descriptor()
if md.ExtensionRanges().Len() == 0 {
return nil
}
type ext struct {
desc protoreflect.FieldDescriptor
val protoreflect.Value
}
var exts []ext
m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
if fd.IsExtension() {
exts = append(exts, ext{fd, v})
}
return true
})
sort.Slice(exts, func(i, j int) bool {
return exts[i].desc.Number() < exts[j].desc.Number()
})
for _, ext := range exts {
// For message set, use the name of the message as the extension name.
name := string(ext.desc.FullName())
if isMessageSet(ext.desc.ContainingMessage()) {
name = strings.TrimSuffix(name, ".message_set_extension")
}
if !ext.desc.IsList() {
if err := w.writeSingularExtension(name, ext.val, ext.desc); err != nil {
return err
}
} else {
lv := ext.val.List()
for i := 0; i < lv.Len(); i++ {
if err := w.writeSingularExtension(name, lv.Get(i), ext.desc); err != nil {
return err
}
}
}
}
return nil
}
func (w *textWriter) writeSingularExtension(name string, v protoreflect.Value, fd protoreflect.FieldDescriptor) error {
fmt.Fprintf(w, "[%s]:", name)
if !w.compact {
w.WriteByte(' ')
}
if err := w.writeSingularValue(v, fd); err != nil {
return err
}
w.WriteByte('\n')
return nil
}
func (w *textWriter) writeIndent() {
if !w.complete {
return
}
for i := 0; i < w.indent*2; i++ {
w.buf = append(w.buf, ' ')
}
w.complete = false
}

Просмотреть файл

@ -1,894 +0,0 @@
// Copyright 2010 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.
package proto
// Functions for parsing the Text protocol buffer format.
// TODO: message sets.
import (
"encoding"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"sync"
"unicode/utf8"
)
// Error string emitted when deserializing Any and fields are already set
const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
type ParseError struct {
Message string
Line int // 1-based line number
Offset int // 0-based byte offset from start of input
}
func (p *ParseError) Error() string {
if p.Line == 1 {
// show offset only for first line
return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
}
return fmt.Sprintf("line %d: %v", p.Line, p.Message)
}
type token struct {
value string
err *ParseError
line int // line number
offset int // byte number from start of input, not start of line
unquoted string // the unquoted version of value, if it was a quoted string
}
func (t *token) String() string {
if t.err == nil {
return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
}
return fmt.Sprintf("parse error: %v", t.err)
}
type textParser struct {
s string // remaining input
done bool // whether the parsing is finished (success or error)
backed bool // whether back() was called
offset, line int
cur token
}
func newTextParser(s string) *textParser {
p := new(textParser)
p.s = s
p.line = 1
p.cur.line = 1
return p
}
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
p.cur.err = pe
p.done = true
return pe
}
// Numbers and identifiers are matched by [-+._A-Za-z0-9]
func isIdentOrNumberChar(c byte) bool {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
return true
case '0' <= c && c <= '9':
return true
}
switch c {
case '-', '+', '.', '_':
return true
}
return false
}
func isWhitespace(c byte) bool {
switch c {
case ' ', '\t', '\n', '\r':
return true
}
return false
}
func isQuote(c byte) bool {
switch c {
case '"', '\'':
return true
}
return false
}
func (p *textParser) skipWhitespace() {
i := 0
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
if p.s[i] == '#' {
// comment; skip to end of line or input
for i < len(p.s) && p.s[i] != '\n' {
i++
}
if i == len(p.s) {
break
}
}
if p.s[i] == '\n' {
p.line++
}
i++
}
p.offset += i
p.s = p.s[i:len(p.s)]
if len(p.s) == 0 {
p.done = true
}
}
func (p *textParser) advance() {
// Skip whitespace
p.skipWhitespace()
if p.done {
return
}
// Start of non-whitespace
p.cur.err = nil
p.cur.offset, p.cur.line = p.offset, p.line
p.cur.unquoted = ""
switch p.s[0] {
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
// Single symbol
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
case '"', '\'':
// Quoted string
i := 1
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
if p.s[i] == '\\' && i+1 < len(p.s) {
// skip escaped char
i++
}
i++
}
if i >= len(p.s) || p.s[i] != p.s[0] {
p.errorf("unmatched quote")
return
}
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
if err != nil {
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
return
}
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
p.cur.unquoted = unq
default:
i := 0
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
i++
}
if i == 0 {
p.errorf("unexpected byte %#x", p.s[0])
return
}
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
}
p.offset += len(p.cur.value)
}
var (
errBadUTF8 = errors.New("proto: bad UTF-8")
)
func unquoteC(s string, quote rune) (string, error) {
// This is based on C++'s tokenizer.cc.
// Despite its name, this is *not* parsing C syntax.
// For instance, "\0" is an invalid quoted string.
// Avoid allocation in trivial cases.
simple := true
for _, r := range s {
if r == '\\' || r == quote {
simple = false
break
}
}
if simple {
return s, nil
}
buf := make([]byte, 0, 3*len(s)/2)
for len(s) > 0 {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", errBadUTF8
}
s = s[n:]
if r != '\\' {
if r < utf8.RuneSelf {
buf = append(buf, byte(r))
} else {
buf = append(buf, string(r)...)
}
continue
}
ch, tail, err := unescape(s)
if err != nil {
return "", err
}
buf = append(buf, ch...)
s = tail
}
return string(buf), nil
}
func unescape(s string) (ch string, tail string, err error) {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", "", errBadUTF8
}
s = s[n:]
switch r {
case 'a':
return "\a", s, nil
case 'b':
return "\b", s, nil
case 'f':
return "\f", s, nil
case 'n':
return "\n", s, nil
case 'r':
return "\r", s, nil
case 't':
return "\t", s, nil
case 'v':
return "\v", s, nil
case '?':
return "?", s, nil // trigraph workaround
case '\'', '"', '\\':
return string(r), s, nil
case '0', '1', '2', '3', '4', '5', '6', '7':
if len(s) < 2 {
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
}
ss := string(r) + s[:2]
s = s[2:]
i, err := strconv.ParseUint(ss, 8, 8)
if err != nil {
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
}
return string([]byte{byte(i)}), s, nil
case 'x', 'X', 'u', 'U':
var n int
switch r {
case 'x', 'X':
n = 2
case 'u':
n = 4
case 'U':
n = 8
}
if len(s) < n {
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
}
ss := s[:n]
s = s[n:]
i, err := strconv.ParseUint(ss, 16, 64)
if err != nil {
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
}
if r == 'x' || r == 'X' {
return string([]byte{byte(i)}), s, nil
}
if i > utf8.MaxRune {
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
}
return string(i), s, nil
}
return "", "", fmt.Errorf(`unknown escape \%c`, r)
}
// Back off the parser by one token. Can only be done between calls to next().
// It makes the next advance() a no-op.
func (p *textParser) back() { p.backed = true }
// Advances the parser and returns the new current token.
func (p *textParser) next() *token {
if p.backed || p.done {
p.backed = false
return &p.cur
}
p.advance()
if p.done {
p.cur.value = ""
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
// Look for multiple quoted strings separated by whitespace,
// and concatenate them.
cat := p.cur
for {
p.skipWhitespace()
if p.done || !isQuote(p.s[0]) {
break
}
p.advance()
if p.cur.err != nil {
return &p.cur
}
cat.value += " " + p.cur.value
cat.unquoted += p.cur.unquoted
}
p.done = false // parser may have seen EOF, but we want to return cat
p.cur = cat
}
return &p.cur
}
func (p *textParser) consumeToken(s string) error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != s {
p.back()
return p.errorf("expected %q, found %q", s, tok.value)
}
return nil
}
// Return a requiredNotSetError indicating which required field was not set.
func (p *textParser) missingRequiredFieldError(sv reflect.Value) *requiredNotSetError {
st := sv.Type()
sprops := GetProperties(st)
for i := 0; i < st.NumField(); i++ {
if !isNil(sv.Field(i)) {
continue
}
props := sprops.Prop[i]
if props.Required {
return &requiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
}
}
return &requiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
}
// Returns the index in the struct for the named field, as well as the parsed tag properties.
func structFieldByName(sprops *textStructProperties, name string) (int, *Properties, bool) {
i, ok := sprops.decoderOrigNames[name]
if ok {
return i, sprops.Prop[i], true
}
return -1, nil, false
}
// Consume a ':' from the input stream (if the next token is a colon),
// returning an error if a colon is needed but not present.
func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ":" {
// Colon is optional when the field is a group or message.
needColon := true
switch props.Wire {
case "group":
needColon = false
case "bytes":
// A "bytes" field is either a message, a string, or a repeated field;
// those three become *T, *string and []T respectively, so we can check for
// this field being a pointer to a non-string.
if typ.Kind() == reflect.Ptr {
// *T or *string
if typ.Elem().Kind() == reflect.String {
break
}
} else if typ.Kind() == reflect.Slice {
// []T or []*T
if typ.Elem().Kind() != reflect.Ptr {
break
}
} else if typ.Kind() == reflect.String {
// The proto3 exception is for a string field,
// which requires a colon.
break
}
needColon = false
}
if needColon {
return p.errorf("expected ':', found %q", tok.value)
}
p.back()
}
return nil
}
var textPropertiesCache sync.Map // map[reflect.Type]*textStructProperties
type textStructProperties struct {
*StructProperties
reqCount int
decoderOrigNames map[string]int
}
func getTextProperties(t reflect.Type) *textStructProperties {
if p, ok := textPropertiesCache.Load(t); ok {
return p.(*textStructProperties)
}
prop := &textStructProperties{StructProperties: GetProperties(t)}
reqCount := 0
prop.decoderOrigNames = make(map[string]int)
for i, p := range prop.Prop {
if strings.HasPrefix(p.Name, "XXX_") {
// Internal fields should not appear in tags/origNames maps.
// They are handled specially when encoding and decoding.
continue
}
if p.Required {
reqCount++
}
prop.decoderOrigNames[p.OrigName] = i
}
prop.reqCount = reqCount
textPropertiesCache.Store(t, prop)
return prop
}
func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
st := sv.Type()
sprops := getTextProperties(st)
reqCount := sprops.reqCount
var reqFieldErr error
fieldSet := make(map[string]bool)
// A struct is a sequence of "name: value", terminated by one of
// '>' or '}', or the end of the input. A name may also be
// "[extension]" or "[type/url]".
//
// The whole struct can also be an expanded Any message, like:
// [type/url] < ... struct contents ... >
for {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == terminator {
break
}
if tok.value == "[" {
// Looks like an extension or an Any.
//
// TODO: Check whether we need to handle
// namespace rooted names (e.g. ".something.Foo").
extName, err := p.consumeExtName()
if err != nil {
return err
}
if s := strings.LastIndex(extName, "/"); s >= 0 {
// If it contains a slash, it's an Any type URL.
messageName := extName[s+1:]
mt := MessageType(messageName)
if mt == nil {
return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
}
tok = p.next()
if tok.err != nil {
return tok.err
}
// consume an optional colon
if tok.value == ":" {
tok = p.next()
if tok.err != nil {
return tok.err
}
}
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
v := reflect.New(mt.Elem())
if pe := p.readStruct(v.Elem(), terminator); pe != nil {
return pe
}
b, err := Marshal(v.Interface().(Message))
if err != nil {
return p.errorf("failed to marshal message of type %q: %v", messageName, err)
}
if fieldSet["type_url"] {
return p.errorf(anyRepeatedlyUnpacked, "type_url")
}
if fieldSet["value"] {
return p.errorf(anyRepeatedlyUnpacked, "value")
}
sv.FieldByName("TypeUrl").SetString(extName)
sv.FieldByName("Value").SetBytes(b)
fieldSet["type_url"] = true
fieldSet["value"] = true
continue
}
var desc *ExtensionDesc
// This could be faster, but it's functional.
// TODO: Do something smarter than a linear scan.
for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
if d.Name == extName {
desc = d
break
}
if strings.TrimSuffix(d.Name, ".message_set_extension") == extName && isMessageSet(st) {
desc = d
break
}
}
if desc == nil {
return p.errorf("unrecognized extension %q", extName)
}
props := &Properties{}
props.Parse(desc.Tag)
typ := reflect.TypeOf(desc.ExtensionType)
if err := p.checkForColon(props, typ); err != nil {
return err
}
rep := isRepeatedExtension(desc)
// Read the extension structure, and set it in
// the value we're constructing.
var ext reflect.Value
if !rep {
ext = reflect.New(typ).Elem()
} else {
ext = reflect.New(typ.Elem()).Elem()
}
if err := p.readAny(ext, props); err != nil {
if _, ok := err.(*requiredNotSetError); !ok {
return err
}
reqFieldErr = err
}
ep := sv.Addr().Interface().(Message)
if !rep {
SetExtension(ep, desc, ext.Interface())
} else {
old, err := GetExtension(ep, desc)
var sl reflect.Value
if err == nil {
sl = reflect.ValueOf(old) // existing slice
} else {
sl = reflect.MakeSlice(typ, 0, 1)
}
sl = reflect.Append(sl, ext)
SetExtension(ep, desc, sl.Interface())
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
continue
}
// This is a normal, non-extension field.
name := tok.value
var dst reflect.Value
fi, props, ok := structFieldByName(sprops, name)
if ok {
dst = sv.Field(fi)
} else if oop, ok := sprops.OneofTypes[name]; ok {
// It is a oneof.
props = oop.Prop
nv := reflect.New(oop.Type.Elem())
dst = nv.Elem().Field(0)
field := sv.Field(oop.Field)
if !field.IsNil() {
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
}
field.Set(nv)
}
if !dst.IsValid() {
return p.errorf("unknown field name %q in %v", name, st)
}
if dst.Kind() == reflect.Map {
// Consume any colon.
if err := p.checkForColon(props, dst.Type()); err != nil {
return err
}
// Construct the map if it doesn't already exist.
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
key := reflect.New(dst.Type().Key()).Elem()
val := reflect.New(dst.Type().Elem()).Elem()
// The map entry should be this sequence of tokens:
// < key : KEY value : VALUE >
// However, implementations may omit key or value, and technically
// we should support them in any order. See b/28924776 for a time
// this went wrong.
tok := p.next()
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
for {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == terminator {
break
}
switch tok.value {
case "key":
if err := p.consumeToken(":"); err != nil {
return err
}
if err := p.readAny(key, props.MapKeyProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
case "value":
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
return err
}
if err := p.readAny(val, props.MapValProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
default:
p.back()
return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
}
}
dst.SetMapIndex(key, val)
continue
}
// Check that it's not already set if it's not a repeated field.
if !props.Repeated && fieldSet[name] {
return p.errorf("non-repeated field %q was repeated", name)
}
if err := p.checkForColon(props, dst.Type()); err != nil {
return err
}
// Parse into the field.
fieldSet[name] = true
if err := p.readAny(dst, props); err != nil {
if _, ok := err.(*requiredNotSetError); !ok {
return err
}
reqFieldErr = err
}
if props.Required {
reqCount--
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
}
if reqCount > 0 {
return p.missingRequiredFieldError(sv)
}
return reqFieldErr
}
// consumeExtName consumes extension name or expanded Any type URL and the
// following ']'. It returns the name or URL consumed.
func (p *textParser) consumeExtName() (string, error) {
tok := p.next()
if tok.err != nil {
return "", tok.err
}
// If extension name or type url is quoted, it's a single token.
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
if err != nil {
return "", err
}
return name, p.consumeToken("]")
}
// Consume everything up to "]"
var parts []string
for tok.value != "]" {
parts = append(parts, tok.value)
tok = p.next()
if tok.err != nil {
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
}
if p.done && tok.value != "]" {
return "", p.errorf("unclosed type_url or extension name")
}
}
return strings.Join(parts, ""), nil
}
// consumeOptionalSeparator consumes an optional semicolon or comma.
// It is used in readStruct to provide backward compatibility.
func (p *textParser) consumeOptionalSeparator() error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ";" && tok.value != "," {
p.back()
}
return nil
}
func (p *textParser) readAny(v reflect.Value, props *Properties) error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == "" {
return p.errorf("unexpected EOF")
}
switch fv := v; fv.Kind() {
case reflect.Slice:
at := v.Type()
if at.Elem().Kind() == reflect.Uint8 {
// Special case for []byte
if tok.value[0] != '"' && tok.value[0] != '\'' {
// Deliberately written out here, as the error after
// this switch statement would write "invalid []byte: ...",
// which is not as user-friendly.
return p.errorf("invalid string: %v", tok.value)
}
bytes := []byte(tok.unquoted)
fv.Set(reflect.ValueOf(bytes))
return nil
}
// Repeated field.
if tok.value == "[" {
// Repeated field with list notation, like [1,2,3].
for {
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
err := p.readAny(fv.Index(fv.Len()-1), props)
if err != nil {
return err
}
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == "]" {
break
}
if tok.value != "," {
return p.errorf("Expected ']' or ',' found %q", tok.value)
}
}
return nil
}
// One value of the repeated field.
p.back()
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
return p.readAny(fv.Index(fv.Len()-1), props)
case reflect.Bool:
// true/1/t/True or false/f/0/False.
switch tok.value {
case "true", "1", "t", "True":
fv.SetBool(true)
return nil
case "false", "0", "f", "False":
fv.SetBool(false)
return nil
}
case reflect.Float32, reflect.Float64:
v := tok.value
// Ignore 'f' for compatibility with output generated by C++, but don't
// remove 'f' when the value is "-inf" or "inf".
if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
v = v[:len(v)-1]
}
if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
fv.SetFloat(f)
return nil
}
case reflect.Int32:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
fv.SetInt(x)
return nil
}
if len(props.Enum) == 0 {
break
}
m := EnumValueMap(props.Enum)
if m == nil {
break
}
x, ok := m[tok.value]
if !ok {
break
}
fv.SetInt(int64(x))
return nil
case reflect.Int64:
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Ptr:
// A basic field (indirected through pointer), or a repeated message/group
p.back()
fv.Set(reflect.New(fv.Type().Elem()))
return p.readAny(fv.Elem(), props)
case reflect.String:
if tok.value[0] == '"' || tok.value[0] == '\'' {
fv.SetString(tok.unquoted)
return nil
}
case reflect.Struct:
var terminator string
switch tok.value {
case "{":
terminator = "}"
case "<":
terminator = ">"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
// TODO: Handle nested messages which implement encoding.TextUnmarshaler.
return p.readStruct(fv, terminator)
case reflect.Uint32:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
fv.SetUint(uint64(x))
return nil
}
case reflect.Uint64:
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
fv.SetUint(x)
return nil
}
}
return p.errorf("invalid %v: %v", v.Type(), tok.value)
}
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
// before starting to unmarshal, so any existing data in pb is always removed.
// If a required field is not set and no other error occurs,
// UnmarshalText returns *requiredNotSetError.
func UnmarshalText(s string, pb Message) error {
if unmarshalTextAlt != nil {
return unmarshalTextAlt(s, pb) // populated by hooks_enabled.go
}
if um, ok := pb.(encoding.TextUnmarshaler); ok {
return um.UnmarshalText([]byte(s))
}
pb.Reset()
v := reflect.ValueOf(pb)
return newTextParser(s).readStruct(v.Elem(), "")
}

72
proto/wire.go Normal file
Просмотреть файл

@ -0,0 +1,72 @@
// 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.
package proto
import (
protoV2 "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/runtime/protoimpl"
)
// Size returns the size in bytes of the wire-format encoding of m.
func Size(m Message) int {
if m == nil {
return 0
}
mi := protoimpl.X.ProtoMessageV2Of(m)
return protoV2.Size(mi)
}
// Marshal returns the wire-format encoding of m.
func Marshal(m Message) ([]byte, error) {
b, err := marshalAppend(nil, m, false)
if b == nil {
b = zeroBytes
}
return b, err
}
var zeroBytes = make([]byte, 0, 0)
func marshalAppend(buf []byte, m Message, deterministic bool) ([]byte, error) {
if m == nil {
return nil, ErrNil
}
mi := protoimpl.X.ProtoMessageV2Of(m)
nbuf, err := protoV2.MarshalOptions{
Deterministic: deterministic,
AllowPartial: true,
}.MarshalAppend(buf, mi)
if err != nil {
return buf, err
}
if len(buf) == len(nbuf) {
if !mi.ProtoReflect().IsValid() {
return buf, ErrNil
}
}
return nbuf, checkRequiredNotSet(mi)
}
// Unmarshal parses a wire-format message in b and places the decoded results in m.
//
// Unmarshal resets m before starting to unmarshal, so any existing data in m is always
// removed. Use UnmarshalMerge to preserve and append to existing data.
func Unmarshal(b []byte, m Message) error {
m.Reset()
return UnmarshalMerge(b, m)
}
// UnmarshalMerge parses a wire-format message in b and places the decoded results in m.
func UnmarshalMerge(b []byte, m Message) error {
mi := protoimpl.X.ProtoMessageV2Of(m)
err := protoV2.UnmarshalOptions{
AllowPartial: true,
Merge: true,
}.Unmarshal(b, mi)
if err != nil {
return err
}
return checkRequiredNotSet(mi)
}

Просмотреть файл

@ -9,17 +9,18 @@ import (
"testing"
"github.com/golang/protobuf/proto"
tpb "github.com/golang/protobuf/proto/proto3_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
var msgBlackhole = new(tpb.Message)
var msgBlackhole = new(pb3.Message)
// BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and
// 2 bytes long).
func BenchmarkVarint32ArraySmall(b *testing.B) {
for i := uint(1); i <= 10; i++ {
dist := genInt32Dist([7]int{0, 3, 1}, 1<<i)
raw, err := proto.Marshal(&tpb.Message{
raw, err := proto.Marshal(&pb3.Message{
ShortKey: dist,
})
if err != nil {
@ -44,7 +45,7 @@ func BenchmarkVarint32ArraySmall(b *testing.B) {
func BenchmarkVarint32ArrayLarge(b *testing.B) {
for i := uint(1); i <= 10; i++ {
dist := genInt32Dist([7]int{0, 1, 2, 4, 8, 1, 1}, 1<<i)
raw, err := proto.Marshal(&tpb.Message{
raw, err := proto.Marshal(&pb3.Message{
ShortKey: dist,
})
if err != nil {
@ -69,7 +70,7 @@ func BenchmarkVarint32ArrayLarge(b *testing.B) {
func BenchmarkVarint64ArraySmall(b *testing.B) {
for i := uint(1); i <= 10; i++ {
dist := genUint64Dist([11]int{0, 3, 1}, 1<<i)
raw, err := proto.Marshal(&tpb.Message{
raw, err := proto.Marshal(&pb3.Message{
Key: dist,
})
if err != nil {
@ -94,7 +95,7 @@ func BenchmarkVarint64ArraySmall(b *testing.B) {
func BenchmarkVarint64ArrayLarge(b *testing.B) {
for i := uint(1); i <= 10; i++ {
dist := genUint64Dist([11]int{0, 1, 1, 2, 4, 8, 16, 32, 16, 1, 1}, 1<<i)
raw, err := proto.Marshal(&tpb.Message{
raw, err := proto.Marshal(&pb3.Message{
Key: dist,
})
if err != nil {
@ -121,9 +122,9 @@ func BenchmarkVarint64ArrayMixed(b *testing.B) {
dist := genUint64Dist([11]int{0, 0, 0, 4, 6, 4, 0, 0, 0, 0, 0}, int(i))
// number of sub fields
for k := uint(1); k <= 1<<10; k <<= 2 {
msg := &tpb.Message{}
msg := &pb3.Message{}
for m := uint(0); m < k; m++ {
msg.Children = append(msg.Children, &tpb.Message{
msg.Children = append(msg.Children, &pb3.Message{
Key: dist,
})
}
@ -213,7 +214,7 @@ func genUint64Dist(dist [11]int, count int) (dest []uint64) {
// BenchmarkDecodeEmpty measures the overhead of doing the minimal possible decode.
func BenchmarkDecodeEmpty(b *testing.B) {
raw, err := proto.Marshal(&tpb.Message{})
raw, err := proto.Marshal(&pb3.Message{})
if err != nil {
b.Error("wrong encode", err)
}

Просмотреть файл

@ -9,8 +9,9 @@ import (
"testing"
"github.com/golang/protobuf/proto"
tpb "github.com/golang/protobuf/proto/proto3_proto"
"github.com/golang/protobuf/ptypes"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
var (
@ -25,14 +26,14 @@ func BenchmarkAny(b *testing.B) {
for i := uint(0); i <= 10; i++ {
b.Run(strconv.Itoa(quantum<<i), func(b *testing.B) {
for k := 0; k < b.N; k++ {
inner := &tpb.Message{
inner := &pb3.Message{
Data: data[:quantum<<i],
}
outer, err := ptypes.MarshalAny(inner)
if err != nil {
b.Error("wrong encode", err)
}
raw, err := proto.Marshal(&tpb.Message{
raw, err := proto.Marshal(&pb3.Message{
Anything: outer,
})
if err != nil {
@ -47,7 +48,7 @@ func BenchmarkAny(b *testing.B) {
// BenchmarkEmpy measures the overhead of doing the minimal possible encode.
func BenchmarkEmpy(b *testing.B) {
for i := 0; i < b.N; i++ {
raw, err := proto.Marshal(&tpb.Message{})
raw, err := proto.Marshal(&pb3.Message{})
if err != nil {
b.Error("wrong encode", err)
}

177
proto/wire_size_test.go Normal file
Просмотреть файл

@ -0,0 +1,177 @@
// Copyright 2012 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.
package proto_test
import (
"log"
"math"
"strings"
"testing"
"github.com/golang/protobuf/proto"
pb2 "github.com/golang/protobuf/internal/testprotos/proto2_proto"
pb3 "github.com/golang/protobuf/internal/testprotos/proto3_proto"
)
var messageWithExtension1 = &pb2.MyMessage{Count: proto.Int32(7)}
// messageWithExtension2 is in equal_test.go.
var messageWithExtension3 = &pb2.MyMessage{Count: proto.Int32(8)}
func init() {
if err := proto.SetExtension(messageWithExtension1, pb2.E_Ext_More, &pb2.Ext{Data: proto.String("Abbott")}); err != nil {
log.Panicf("proto.SetExtension: %v", err)
}
if err := proto.SetExtension(messageWithExtension3, pb2.E_Ext_More, &pb2.Ext{Data: proto.String("Costello")}); err != nil {
log.Panicf("proto.SetExtension: %v", err)
}
// Force messageWithExtension3 to have the extension encoded.
proto.Marshal(messageWithExtension3)
}
// non-pointer custom message
type nonptrMessage struct{}
func (m nonptrMessage) ProtoMessage() {}
func (m nonptrMessage) Reset() {}
func (m nonptrMessage) String() string { return "" }
func (m nonptrMessage) Marshal() ([]byte, error) {
return []byte{42}, nil
}
var SizeTests = []struct {
desc string
pb proto.Message
}{
{"empty", &pb2.OtherMessage{}},
// Basic types.
{"bool", &pb2.Defaults{F_Bool: proto.Bool(true)}},
{"int32", &pb2.Defaults{F_Int32: proto.Int32(12)}},
{"negative int32", &pb2.Defaults{F_Int32: proto.Int32(-1)}},
{"small int64", &pb2.Defaults{F_Int64: proto.Int64(1)}},
{"big int64", &pb2.Defaults{F_Int64: proto.Int64(1 << 20)}},
{"negative int64", &pb2.Defaults{F_Int64: proto.Int64(-1)}},
{"fixed32", &pb2.Defaults{F_Fixed32: proto.Uint32(71)}},
{"fixed64", &pb2.Defaults{F_Fixed64: proto.Uint64(72)}},
{"uint32", &pb2.Defaults{F_Uint32: proto.Uint32(123)}},
{"uint64", &pb2.Defaults{F_Uint64: proto.Uint64(124)}},
{"float", &pb2.Defaults{F_Float: proto.Float32(12.6)}},
{"double", &pb2.Defaults{F_Double: proto.Float64(13.9)}},
{"string", &pb2.Defaults{F_String: proto.String("niles")}},
{"bytes", &pb2.Defaults{F_Bytes: []byte("wowsa")}},
{"bytes, empty", &pb2.Defaults{F_Bytes: []byte{}}},
{"sint32", &pb2.Defaults{F_Sint32: proto.Int32(65)}},
{"sint64", &pb2.Defaults{F_Sint64: proto.Int64(67)}},
{"enum", &pb2.Defaults{F_Enum: pb2.Defaults_BLUE.Enum()}},
// Repeated.
{"empty repeated bool", &pb2.MoreRepeated{Bools: []bool{}}},
{"repeated bool", &pb2.MoreRepeated{Bools: []bool{false, true, true, false}}},
{"packed repeated bool", &pb2.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}},
{"repeated int32", &pb2.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}},
{"repeated int32 packed", &pb2.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}},
{"repeated int64 packed", &pb2.MoreRepeated{Int64SPacked: []int64{
// Need enough large numbers to verify that the header is counting the number of bytes
// for the field, not the number of elements.
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62,
}}},
{"repeated string", &pb2.MoreRepeated{Strings: []string{"r", "ken", "gri"}}},
{"repeated fixed", &pb2.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}},
// Nested.
{"nested", &pb2.OldMessage{Nested: &pb2.OldMessage_Nested{Name: proto.String("whatever")}}},
{"group", &pb2.GroupOld{G: &pb2.GroupOld_G{X: proto.Int32(12345)}}},
// Other things.
{"unrecognized", &pb2.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}},
{"extension (unencoded)", messageWithExtension1},
{"extension (encoded)", messageWithExtension3},
// proto3 message
{"proto3 empty", &pb3.Message{}},
{"proto3 bool", &pb3.Message{TrueScotsman: true}},
{"proto3 int64", &pb3.Message{ResultCount: 1}},
{"proto3 uint32", &pb3.Message{HeightInCm: 123}},
{"proto3 float", &pb3.Message{Score: 12.6}},
{"proto3 string", &pb3.Message{Name: "Snezana"}},
{"proto3 bytes", &pb3.Message{Data: []byte("wowsa")}},
{"proto3 bytes, empty", &pb3.Message{Data: []byte{}}},
{"proto3 enum", &pb3.Message{Hilarity: pb3.Message_PUNS}},
{"proto3 map field with empty bytes", &pb3.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}},
{"map field", &pb2.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}},
{"map field with message", &pb2.MessageWithMap{MsgMapping: map[int64]*pb2.FloatingPoint{0x7001: &pb2.FloatingPoint{F: proto.Float64(2.0)}}}},
{"map field with bytes", &pb2.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}},
{"map field with empty bytes", &pb2.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}},
{"map field with big entry", &pb2.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}},
{"map field with big key and val", &pb2.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}},
{"map field with big numeric key", &pb2.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}},
{"oneof not set", &pb2.Oneof{}},
{"oneof bool", &pb2.Oneof{Union: &pb2.Oneof_F_Bool{true}}},
{"oneof zero int32", &pb2.Oneof{Union: &pb2.Oneof_F_Int32{0}}},
{"oneof big int32", &pb2.Oneof{Union: &pb2.Oneof_F_Int32{1 << 20}}},
{"oneof int64", &pb2.Oneof{Union: &pb2.Oneof_F_Int64{42}}},
{"oneof fixed32", &pb2.Oneof{Union: &pb2.Oneof_F_Fixed32{43}}},
{"oneof fixed64", &pb2.Oneof{Union: &pb2.Oneof_F_Fixed64{44}}},
{"oneof uint32", &pb2.Oneof{Union: &pb2.Oneof_F_Uint32{45}}},
{"oneof uint64", &pb2.Oneof{Union: &pb2.Oneof_F_Uint64{46}}},
{"oneof float", &pb2.Oneof{Union: &pb2.Oneof_F_Float{47.1}}},
{"oneof double", &pb2.Oneof{Union: &pb2.Oneof_F_Double{48.9}}},
{"oneof string", &pb2.Oneof{Union: &pb2.Oneof_F_String{"Rhythmic Fman"}}},
{"oneof bytes", &pb2.Oneof{Union: &pb2.Oneof_F_Bytes{[]byte("let go")}}},
{"oneof sint32", &pb2.Oneof{Union: &pb2.Oneof_F_Sint32{50}}},
{"oneof sint64", &pb2.Oneof{Union: &pb2.Oneof_F_Sint64{51}}},
{"oneof enum", &pb2.Oneof{Union: &pb2.Oneof_F_Enum{pb2.MyMessage_BLUE}}},
{"message for oneof", &pb2.GoTestField{Label: proto.String("k"), Type: proto.String("v")}},
{"oneof message", &pb2.Oneof{Union: &pb2.Oneof_F_Message{&pb2.GoTestField{Label: proto.String("k"), Type: proto.String("v")}}}},
{"oneof group", &pb2.Oneof{Union: &pb2.Oneof_FGroup{&pb2.Oneof_F_Group{X: proto.Int32(52)}}}},
{"oneof largest tag", &pb2.Oneof{Union: &pb2.Oneof_F_Largest_Tag{1}}},
{"multiple oneofs", &pb2.Oneof{Union: &pb2.Oneof_F_Int32{1}, Tormato: &pb2.Oneof_Value{2}}},
{"non-pointer message", nonptrMessage{}},
}
func TestSize(t *testing.T) {
for _, tc := range SizeTests {
t.Run(tc.desc, func(t *testing.T) {
size := proto.Size(tc.pb)
b, err := proto.Marshal(tc.pb)
if err != nil {
t.Errorf("%v: Marshal failed: %v", tc.desc, err)
return
}
if size != len(b) {
t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b))
t.Logf("%v: bytes: %#v", tc.desc, b)
}
})
}
}
func TestVarintSize(t *testing.T) {
// Check the edge cases carefully.
testCases := []struct {
n uint64
size int
}{
{0, 1},
{1, 1},
{127, 1},
{128, 2},
{16383, 2},
{16384, 3},
{math.MaxInt64, 9},
{math.MaxInt64 + 1, 10},
}
for _, tc := range testCases {
size := proto.SizeVarint(tc.n)
if size != tc.size {
t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size)
}
}
}

Просмотреть файл

@ -8,6 +8,8 @@ package proto
func Bool(v bool) *bool { return &v }
// Int stores v in a new int32 value and returns a pointer to it.
//
// Deprecated: Use Int32 instead.
func Int(v int) *int32 { return Int32(int32(v)) }
// Int32 stores v in a new int32 value and returns a pointer to it.
@ -16,17 +18,17 @@ func Int32(v int32) *int32 { return &v }
// Int64 stores v in a new int64 value and returns a pointer to it.
func Int64(v int64) *int64 { return &v }
// Float32 stores v in a new float32 value and returns a pointer to it.
func Float32(v float32) *float32 { return &v }
// Float64 stores v in a new float64 value and returns a pointer to it.
func Float64(v float64) *float64 { return &v }
// Uint32 stores v in a new uint32 value and returns a pointer to it.
func Uint32(v uint32) *uint32 { return &v }
// Uint64 stores v in a new uint64 value and returns a pointer to it.
func Uint64(v uint64) *uint64 { return &v }
// Float32 stores v in a new float32 value and returns a pointer to it.
func Float32(v float32) *float32 { return &v }
// Float64 stores v in a new float64 value and returns a pointer to it.
func Float64(v float64) *float64 { return &v }
// String stores v in a new string value and returns a pointer to it.
func String(v string) *string { return &v }

Просмотреть файл

@ -40,7 +40,7 @@ import (
func init() {
fmt.Fprint(os.Stderr,
"WARNING: Package github.com/golang/protobuf/protoc-gen-go/generator is deprecated.\n"+
"WARNING: Package \"github.com/golang/protobuf/protoc-gen-go/generator\" is deprecated.\n"+
"\tA future release of golang/protobuf will delete this package,\n"+
"\twhich has long been excluded from the compatibility promise.\n\n")
}

Просмотреть файл

@ -1,108 +0,0 @@
// Copyright 2013 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.
package generator
import (
"testing"
"github.com/golang/protobuf/protoc-gen-go/descriptor"
)
func TestCamelCase(t *testing.T) {
tests := []struct {
in, want string
}{
{"one", "One"},
{"one_two", "OneTwo"},
{"_my_field_name_2", "XMyFieldName_2"},
{"Something_Capped", "Something_Capped"},
{"my_Name", "My_Name"},
{"OneTwo", "OneTwo"},
{"_", "X"},
{"_a_", "XA_"},
}
for _, tc := range tests {
if got := CamelCase(tc.in); got != tc.want {
t.Errorf("CamelCase(%q) = %q, want %q", tc.in, got, tc.want)
}
}
}
func TestGoPackageOption(t *testing.T) {
tests := []struct {
in string
impPath GoImportPath
pkg GoPackageName
ok bool
}{
{"", "", "", false},
{"foo", "", "foo", true},
{"github.com/golang/bar", "github.com/golang/bar", "bar", true},
{"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true},
{"github.com/golang/string", "github.com/golang/string", "string", true},
}
for _, tc := range tests {
d := &FileDescriptor{
FileDescriptorProto: &descriptor.FileDescriptorProto{
Options: &descriptor.FileOptions{
GoPackage: &tc.in,
},
},
}
impPath, pkg, ok := d.goPackageOption()
if impPath != tc.impPath || pkg != tc.pkg || ok != tc.ok {
t.Errorf("go_package = %q => (%q, %q, %t), want (%q, %q, %t)", tc.in,
impPath, pkg, ok, tc.impPath, tc.pkg, tc.ok)
}
}
}
func TestPackageNames(t *testing.T) {
g := New()
g.packageNames = make(map[GoImportPath]GoPackageName)
g.usedPackageNames = make(map[GoPackageName]bool)
for _, test := range []struct {
importPath GoImportPath
want GoPackageName
}{
{"github.com/golang/foo", "foo"},
{"github.com/golang/second/package/named/foo", "foo1"},
{"github.com/golang/third/package/named/foo", "foo2"},
{"github.com/golang/conflicts/with/predeclared/ident/string", "string1"},
} {
if got := g.GoPackageName(test.importPath); got != test.want {
t.Errorf("GoPackageName(%v) = %v, want %v", test.importPath, got, test.want)
}
}
}
func TestUnescape(t *testing.T) {
tests := []struct {
in string
out string
}{
// successful cases, including all kinds of escapes
{"", ""},
{"foo bar baz frob nitz", "foo bar baz frob nitz"},
{`\000\001\002\003\004\005\006\007`, string([]byte{0, 1, 2, 3, 4, 5, 6, 7})},
{`\a\b\f\n\r\t\v\\\?\'\"`, string([]byte{'\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '?', '\'', '"'})},
{`\x10\x20\x30\x40\x50\x60\x70\x80`, string([]byte{16, 32, 48, 64, 80, 96, 112, 128})},
// variable length octal escapes
{`\0\018\222\377\3\04\005\6\07`, string([]byte{0, 1, '8', 0222, 255, 3, 4, 5, 6, 7})},
// malformed escape sequences left as is
{"foo \\g bar", "foo \\g bar"},
{"foo \\xg0 bar", "foo \\xg0 bar"},
{"\\", "\\"},
{"\\x", "\\x"},
{"\\xf", "\\xf"},
{"\\777", "\\777"}, // overflows byte
}
for _, tc := range tests {
s := unescape(tc.in)
if s != tc.out {
t.Errorf("doUnescape(%q) = %q; should have been %q", tc.in, s, tc.out)
}
}
}

Просмотреть файл

@ -4,111 +4,157 @@
package ptypes
// This file implements functions to marshal proto.Message to/from
// google.protobuf.Any message.
import (
"fmt"
"reflect"
"strings"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/any"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/runtime/protoimpl"
anypb "github.com/golang/protobuf/ptypes/any"
)
const googleApis = "type.googleapis.com/"
const urlPrefix = "type.googleapis.com/"
// AnyMessageName returns the name of the message contained in a google.protobuf.Any message.
//
// Note that regular type assertions should be done using the Is
// function. AnyMessageName is provided for less common use cases like filtering a
// sequence of Any messages based on a set of allowed message type names.
func AnyMessageName(any *any.Any) (string, error) {
// AnyMessageName returns the message name contained in an anypb.Any message.
// Most type assertions should use the Is function instead.
func AnyMessageName(any *anypb.Any) (string, error) {
name, err := anyMessageName(any)
return string(name), err
}
func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
if any == nil {
return "", fmt.Errorf("message is nil")
}
slash := strings.LastIndex(any.TypeUrl, "/")
if slash < 0 {
name := protoreflect.FullName(any.TypeUrl)
if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 {
name = name[i+len("/"):]
}
if !name.IsValid() {
return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
}
return any.TypeUrl[slash+1:], nil
return name, nil
}
// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any.
func MarshalAny(pb proto.Message) (*any.Any, error) {
value, err := proto.Marshal(pb)
// MarshalAny marshals the given message m into an anypb.Any message.
func MarshalAny(m proto.Message) (*anypb.Any, error) {
if dm, ok := m.(*DynamicAny); ok {
m = dm.Message
}
b, err := proto.Marshal(m)
if err != nil {
return nil, err
}
return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil
}
// DynamicAny is a value that can be passed to UnmarshalAny to automatically
// allocate a proto.Message for the type specified in a google.protobuf.Any
// message. The allocated message is stored in the embedded proto.Message.
//
// Example:
//
// var x ptypes.DynamicAny
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
// fmt.Printf("unmarshaled message: %v", x.Message)
type DynamicAny struct {
proto.Message
}
// Empty returns a new proto.Message of the type specified in a
// google.protobuf.Any message. It returns an error if corresponding message
// type isn't linked in.
func Empty(any *any.Any) (proto.Message, error) {
aname, err := AnyMessageName(any)
// Empty returns a new message of the type specified in an anypb.Any message.
// It returns protoregistry.NotFound if the corresponding message type could not
// be resolved in the global registry.
func Empty(any *anypb.Any) (proto.Message, error) {
name, err := anyMessageName(any)
if err != nil {
return nil, err
}
t := proto.MessageType(aname)
if t == nil {
return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
mt, err := protoregistry.GlobalTypes.FindMessageByName(name)
if err != nil {
return nil, err
}
return reflect.New(t.Elem()).Interface().(proto.Message), nil
return protoimpl.X.ProtoMessageV1Of(mt.New().Interface()), nil
}
// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any
// message and places the decoded result in pb. It returns an error if type of
// contents of Any message does not match type of pb message.
// UnmarshalAny unmarshals the encoded value contained in the anypb.Any message
// into the provided message m. It returns an error if the target message
// does not match the type in the Any message or if an unmarshal error occurs.
//
// pb can be a proto.Message, or a *DynamicAny.
func UnmarshalAny(any *any.Any, pb proto.Message) error {
if d, ok := pb.(*DynamicAny); ok {
if d.Message == nil {
// The target message m may be a *DynamicAny message. If the underlying message
// type could not be resolved, then this returns protoregistry.NotFound.
func UnmarshalAny(any *anypb.Any, m proto.Message) error {
if dm, ok := m.(*DynamicAny); ok {
if dm.Message == nil {
var err error
d.Message, err = Empty(any)
dm.Message, err = Empty(any)
if err != nil {
return err
}
}
return UnmarshalAny(any, d.Message)
m = dm.Message
}
aname, err := AnyMessageName(any)
anyName, err := AnyMessageName(any)
if err != nil {
return err
}
mname := proto.MessageName(pb)
if aname != mname {
return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
msgName := proto.MessageName(m)
if anyName != msgName {
return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName)
}
return proto.Unmarshal(any.Value, pb)
return proto.Unmarshal(any.Value, m)
}
// Is returns true if any value contains a given message type.
func Is(any *any.Any, pb proto.Message) bool {
// The following is equivalent to AnyMessageName(any) == proto.MessageName(pb),
// but it avoids scanning TypeUrl for the slash.
if any == nil {
// Is reports whether the Any message contains a message of the specified type.
func Is(any *anypb.Any, m proto.Message) bool {
if any == nil || m == nil {
return false
}
name := proto.MessageName(pb)
prefix := len(any.TypeUrl) - len(name)
return prefix >= 1 && any.TypeUrl[prefix-1] == '/' && any.TypeUrl[prefix:] == name
name := proto.MessageName(m)
if !strings.HasSuffix(any.TypeUrl, name) {
return false
}
return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/'
}
// DynamicAny is a value that can be passed to UnmarshalAny to automatically
// allocate a proto.Message for the type specified in an anypb.Any message.
// The allocated message is stored in the embedded proto.Message.
//
// Example:
// var x ptypes.DynamicAny
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
// fmt.Printf("unmarshaled message: %v", x.Message)
type DynamicAny struct{ proto.Message }
func (m DynamicAny) String() string {
if m.Message == nil {
return "<nil>"
}
return m.Message.String()
}
func (m DynamicAny) Reset() {
if m.Message == nil {
return
}
m.Message.Reset()
}
func (m DynamicAny) ProtoMessage() {
return
}
func (m DynamicAny) ProtoReflect() protoreflect.Message {
if m.Message == nil {
return nil
}
return dynamicAny{protoimpl.X.MessageOf(m.Message)}
}
type dynamicAny struct{ protoreflect.Message }
func (m dynamicAny) Type() protoreflect.MessageType {
return dynamicAnyType{m.Message.Type()}
}
func (m dynamicAny) New() protoreflect.Message {
return dynamicAnyType{m.Message.Type()}.New()
}
func (m dynamicAny) Interface() protoreflect.ProtoMessage {
return DynamicAny{protoimpl.X.ProtoMessageV1Of(m.Message.Interface())}
}
type dynamicAnyType struct{ protoreflect.MessageType }
func (t dynamicAnyType) New() protoreflect.Message {
return dynamicAny{t.MessageType.New()}
}
func (t dynamicAnyType) Zero() protoreflect.Message {
return dynamicAny{t.MessageType.Zero()}
}

Просмотреть файл

@ -5,22 +5,24 @@
package ptypes
import (
"reflect"
"testing"
"github.com/golang/protobuf/proto"
pb "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/golang/protobuf/ptypes/any"
descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
anypb "github.com/golang/protobuf/ptypes/any"
)
func TestMarshalUnmarshal(t *testing.T) {
orig := &any.Any{Value: []byte("test")}
orig := &anypb.Any{Value: []byte("test")}
packed, err := MarshalAny(orig)
if err != nil {
t.Errorf("MarshalAny(%+v): got: _, %v exp: _, nil", orig, err)
}
unpacked := &any.Any{}
unpacked := &anypb.Any{}
err = UnmarshalAny(packed, unpacked)
if err != nil || !proto.Equal(unpacked, orig) {
t.Errorf("got: %v, %+v; want nil, %+v", err, unpacked, orig)
@ -28,48 +30,48 @@ func TestMarshalUnmarshal(t *testing.T) {
}
func TestIs(t *testing.T) {
a, err := MarshalAny(&pb.FileDescriptorProto{})
a, err := MarshalAny(&descriptorpb.FileDescriptorProto{})
if err != nil {
t.Fatal(err)
}
if Is(a, &pb.DescriptorProto{}) {
if Is(a, &descriptorpb.DescriptorProto{}) {
// No spurious match for message names of different length.
t.Error("FileDescriptorProto is not a DescriptorProto, but Is says it is")
}
if Is(a, &pb.EnumDescriptorProto{}) {
if Is(a, &descriptorpb.EnumDescriptorProto{}) {
// No spurious match for message names of equal length.
t.Error("FileDescriptorProto is not an EnumDescriptorProto, but Is says it is")
}
if !Is(a, &pb.FileDescriptorProto{}) {
if !Is(a, &descriptorpb.FileDescriptorProto{}) {
t.Error("FileDescriptorProto is indeed a FileDescriptorProto, but Is says it is not")
}
}
func TestIsDifferentUrlPrefixes(t *testing.T) {
m := &pb.FileDescriptorProto{}
a := &any.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)}
m := &descriptorpb.FileDescriptorProto{}
a := &anypb.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)}
if !Is(a, m) {
t.Errorf("message with type url %q didn't satisfy Is for type %q", a.TypeUrl, proto.MessageName(m))
}
}
func TestIsCornerCases(t *testing.T) {
m := &pb.FileDescriptorProto{}
m := &descriptorpb.FileDescriptorProto{}
if Is(nil, m) {
t.Errorf("message with nil type url incorrectly claimed to be %q", proto.MessageName(m))
}
noPrefix := &any.Any{TypeUrl: proto.MessageName(m)}
if Is(noPrefix, m) {
t.Errorf("message with type url %q incorrectly claimed to be %q", noPrefix.TypeUrl, proto.MessageName(m))
noPrefix := &anypb.Any{TypeUrl: proto.MessageName(m)}
if !Is(noPrefix, m) {
t.Errorf("message with type url %q didn't satisfy Is for type %q", noPrefix.TypeUrl, proto.MessageName(m))
}
shortPrefix := &any.Any{TypeUrl: "/" + proto.MessageName(m)}
shortPrefix := &anypb.Any{TypeUrl: "/" + proto.MessageName(m)}
if !Is(shortPrefix, m) {
t.Errorf("message with type url %q didn't satisfy Is for type %q", shortPrefix.TypeUrl, proto.MessageName(m))
}
}
func TestUnmarshalDynamic(t *testing.T) {
want := &pb.FileDescriptorProto{Name: proto.String("foo")}
want := &descriptorpb.FileDescriptorProto{Name: proto.String("foo")}
a, err := MarshalAny(want)
if err != nil {
t.Fatal(err)
@ -84,7 +86,7 @@ func TestUnmarshalDynamic(t *testing.T) {
}
func TestEmpty(t *testing.T) {
want := &pb.FileDescriptorProto{}
want := &descriptorpb.FileDescriptorProto{}
a, err := MarshalAny(want)
if err != nil {
t.Fatal(err)
@ -99,7 +101,7 @@ func TestEmpty(t *testing.T) {
// that's a valid type_url for a message which shouldn't be linked into this
// test binary. We want an error.
a.TypeUrl = "type.googleapis.com/google.protobuf.compiler.Version"
a.TypeUrl = "type.googleapis.com/google.protobuf.FieldMask"
if _, err := Empty(a); err == nil {
t.Errorf("got no error for an attempt to create a message of type %q, which shouldn't be linked in", a.TypeUrl)
}
@ -110,14 +112,17 @@ func TestEmptyCornerCases(t *testing.T) {
if err == nil {
t.Error("expected Empty for nil to fail")
}
want := &pb.FileDescriptorProto{}
noPrefix := &any.Any{TypeUrl: proto.MessageName(want)}
_, err = Empty(noPrefix)
if err == nil {
t.Errorf("expected Empty for any type %q to fail", noPrefix.TypeUrl)
want := &descriptorpb.FileDescriptorProto{}
noPrefix := &anypb.Any{TypeUrl: proto.MessageName(want)}
got, err := Empty(noPrefix)
if err != nil {
t.Errorf("Empty for any type %q failed: %s", noPrefix.TypeUrl, err)
}
shortPrefix := &any.Any{TypeUrl: "/" + proto.MessageName(want)}
got, err := Empty(shortPrefix)
if !proto.Equal(got, want) {
t.Errorf("Empty for any type %q differs, got %q, want %q", noPrefix.TypeUrl, got, want)
}
shortPrefix := &anypb.Any{TypeUrl: "/" + proto.MessageName(want)}
got, err = Empty(shortPrefix)
if err != nil {
t.Errorf("Empty for any type %q failed: %s", shortPrefix.TypeUrl, err)
}
@ -125,3 +130,37 @@ func TestEmptyCornerCases(t *testing.T) {
t.Errorf("Empty for any type %q differs, got %q, want %q", shortPrefix.TypeUrl, got, want)
}
}
func TestAnyReflect(t *testing.T) {
want := &descriptorpb.FileDescriptorProto{Name: proto.String("foo")}
a, err := MarshalAny(want)
if err != nil {
t.Fatal(err)
}
var got DynamicAny
if err := UnmarshalAny(a, &got); err != nil {
t.Fatal(err)
}
wantName := want.ProtoReflect().Descriptor().FullName()
gotName := got.ProtoReflect().Descriptor().FullName()
if gotName != wantName {
t.Errorf("name mismatch: got %v, want %v", gotName, wantName)
}
wantType := reflect.TypeOf(got)
gotType := reflect.TypeOf(got.ProtoReflect().Interface())
if gotType != wantType {
t.Errorf("ProtoReflect().Interface() round-trip type mismatch: got %v, want %v", gotType, wantType)
}
gotType = reflect.TypeOf(got.ProtoReflect().New().Interface())
if gotType != wantType {
t.Errorf("ProtoReflect().New().Interface() type mismatch: got %v, want %v", gotType, wantType)
}
gotType = reflect.TypeOf(got.ProtoReflect().Type().New().Interface())
if gotType != wantType {
t.Errorf("ProtoReflect().Type().New().Interface() type mismatch: got %v, want %v", gotType, wantType)
}
gotType = reflect.TypeOf(got.ProtoReflect().Type().Zero().Interface())
if gotType != wantType {
t.Errorf("ProtoReflect().Type().Zero().Interface() type mismatch: got %v, want %v", gotType, wantType)
}
}

Просмотреть файл

@ -2,5 +2,5 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ptypes contains code for interacting with well-known types.
// Package ptypes provides functionality for interacting with well-known types.
package ptypes

Просмотреть файл

@ -4,72 +4,69 @@
package ptypes
// This file implements conversions between google.protobuf.Duration
// and time.Duration.
import (
"errors"
"fmt"
"time"
durpb "github.com/golang/protobuf/ptypes/duration"
durationpb "github.com/golang/protobuf/ptypes/duration"
)
// Range of google.protobuf.Duration as specified in duration.proto.
// This is about 10,000 years in seconds.
const (
// Range of a durpb.Duration in seconds, as specified in
// google/protobuf/duration.proto. This is about 10,000 years in seconds.
maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
minSeconds = -maxSeconds
)
// validateDuration determines whether the durpb.Duration is valid according to the
// definition in google/protobuf/duration.proto. A valid durpb.Duration
// may still be too large to fit into a time.Duration (the range of durpb.Duration
// is about 10,000 years, and the range of time.Duration is about 290).
func validateDuration(d *durpb.Duration) error {
if d == nil {
return errors.New("duration: nil Duration")
}
if d.Seconds < minSeconds || d.Seconds > maxSeconds {
return fmt.Errorf("duration: %v: seconds out of range", d)
}
if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
return fmt.Errorf("duration: %v: nanos out of range", d)
}
// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
return fmt.Errorf("duration: %v: seconds and nanos have different signs", d)
}
return nil
}
// Duration converts a durpb.Duration to a time.Duration. Duration
// returns an error if the durpb.Duration is invalid or is too large to be
// represented in a time.Duration.
func Duration(p *durpb.Duration) (time.Duration, error) {
if err := validateDuration(p); err != nil {
// Duration converts a durationpb.Duration to a time.Duration.
// Duration returns an error if dur is invalid or overflows a time.Duration.
func Duration(dur *durationpb.Duration) (time.Duration, error) {
if err := validateDuration(dur); err != nil {
return 0, err
}
d := time.Duration(p.Seconds) * time.Second
if int64(d/time.Second) != p.Seconds {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
d := time.Duration(dur.Seconds) * time.Second
if int64(d/time.Second) != dur.Seconds {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur)
}
if p.Nanos != 0 {
d += time.Duration(p.Nanos) * time.Nanosecond
if (d < 0) != (p.Nanos < 0) {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
if dur.Nanos != 0 {
d += time.Duration(dur.Nanos) * time.Nanosecond
if (d < 0) != (dur.Nanos < 0) {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur)
}
}
return d, nil
}
// DurationProto converts a time.Duration to a durpb.Duration.
func DurationProto(d time.Duration) *durpb.Duration {
// DurationProto converts a time.Duration to a durationpb.Duration.
func DurationProto(d time.Duration) *durationpb.Duration {
nanos := d.Nanoseconds()
secs := nanos / 1e9
nanos -= secs * 1e9
return &durpb.Duration{
Seconds: secs,
return &durationpb.Duration{
Seconds: int64(secs),
Nanos: int32(nanos),
}
}
// validateDuration determines whether the durationpb.Duration is valid
// according to the definition in google/protobuf/duration.proto.
// A valid durpb.Duration may still be too large to fit into a time.Duration
// Note that the range of durationpb.Duration is about 10,000 years,
// while the range of time.Duration is about 290 years.
func validateDuration(dur *durationpb.Duration) error {
if dur == nil {
return errors.New("duration: nil Duration")
}
if dur.Seconds < minSeconds || dur.Seconds > maxSeconds {
return fmt.Errorf("duration: %v: seconds out of range", dur)
}
if dur.Nanos <= -1e9 || dur.Nanos >= 1e9 {
return fmt.Errorf("duration: %v: nanos out of range", dur)
}
// Seconds and Nanos must have the same sign, unless d.Nanos is zero.
if (dur.Seconds < 0 && dur.Nanos > 0) || (dur.Seconds > 0 && dur.Nanos < 0) {
return fmt.Errorf("duration: %v: seconds and nanos have different signs", dur)
}
return nil
}

Просмотреть файл

@ -10,6 +10,7 @@ import (
"time"
"github.com/golang/protobuf/proto"
durpb "github.com/golang/protobuf/ptypes/duration"
)

Просмотреть файл

@ -4,16 +4,15 @@
package ptypes
// This file implements operations on google.protobuf.Timestamp.
import (
"errors"
"fmt"
"time"
tspb "github.com/golang/protobuf/ptypes/timestamp"
timestamppb "github.com/golang/protobuf/ptypes/timestamp"
)
// Range of google.protobuf.Duration as specified in timestamp.proto.
const (
// Seconds field of the earliest valid Timestamp.
// This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
@ -23,17 +22,71 @@ const (
maxValidSeconds = 253402300800
)
// Timestamp converts a timestamppb.Timestamp to a time.Time.
// It returns an error if the argument is invalid.
//
// Unlike most Go functions, if Timestamp returns an error, the first return
// value is not the zero time.Time. Instead, it is the value obtained from the
// time.Unix function when passed the contents of the Timestamp, in the UTC
// locale. This may or may not be a meaningful time; many invalid Timestamps
// do map to valid time.Times.
//
// A nil Timestamp returns an error. The first return value in that case is
// undefined.
func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
// Don't return the zero value on error, because corresponds to a valid
// timestamp. Instead return whatever time.Unix gives us.
var t time.Time
if ts == nil {
t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
} else {
t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
}
return t, validateTimestamp(ts)
}
// TimestampNow returns a google.protobuf.Timestamp for the current time.
func TimestampNow() *timestamppb.Timestamp {
ts, err := TimestampProto(time.Now())
if err != nil {
panic("ptypes: time.Now() out of Timestamp range")
}
return ts
}
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
// It returns an error if the resulting Timestamp is invalid.
func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
ts := &timestamppb.Timestamp{
Seconds: t.Unix(),
Nanos: int32(t.Nanosecond()),
}
if err := validateTimestamp(ts); err != nil {
return nil, err
}
return ts, nil
}
// TimestampString returns the RFC 3339 string for valid Timestamps.
// For invalid Timestamps, it returns an error message in parentheses.
func TimestampString(ts *timestamppb.Timestamp) string {
t, err := Timestamp(ts)
if err != nil {
return fmt.Sprintf("(%v)", err)
}
return t.Format(time.RFC3339Nano)
}
// validateTimestamp determines whether a Timestamp is valid.
// A valid timestamp represents a time in the range
// [0001-01-01, 10000-01-01) and has a Nanos field
// in the range [0, 1e9).
// A valid timestamp represents a time in the range [0001-01-01, 10000-01-01)
// and has a Nanos field in the range [0, 1e9).
//
// If the Timestamp is valid, validateTimestamp returns nil.
// Otherwise, it returns an error that describes
// the problem.
// Otherwise, it returns an error that describes the problem.
//
// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
func validateTimestamp(ts *tspb.Timestamp) error {
// Every valid Timestamp can be represented by a time.Time,
// but the converse is not true.
func validateTimestamp(ts *timestamppb.Timestamp) error {
if ts == nil {
return errors.New("timestamp: nil Timestamp")
}
@ -48,58 +101,3 @@ func validateTimestamp(ts *tspb.Timestamp) error {
}
return nil
}
// Timestamp converts a google.protobuf.Timestamp proto to a time.Time.
// It returns an error if the argument is invalid.
//
// Unlike most Go functions, if Timestamp returns an error, the first return value
// is not the zero time.Time. Instead, it is the value obtained from the
// time.Unix function when passed the contents of the Timestamp, in the UTC
// locale. This may or may not be a meaningful time; many invalid Timestamps
// do map to valid time.Times.
//
// A nil Timestamp returns an error. The first return value in that case is
// undefined.
func Timestamp(ts *tspb.Timestamp) (time.Time, error) {
// Don't return the zero value on error, because corresponds to a valid
// timestamp. Instead return whatever time.Unix gives us.
var t time.Time
if ts == nil {
t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
} else {
t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
}
return t, validateTimestamp(ts)
}
// TimestampNow returns a google.protobuf.Timestamp for the current time.
func TimestampNow() *tspb.Timestamp {
ts, err := TimestampProto(time.Now())
if err != nil {
panic("ptypes: time.Now() out of Timestamp range")
}
return ts
}
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
// It returns an error if the resulting Timestamp is invalid.
func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
ts := &tspb.Timestamp{
Seconds: t.Unix(),
Nanos: int32(t.Nanosecond()),
}
if err := validateTimestamp(ts); err != nil {
return nil, err
}
return ts, nil
}
// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid
// Timestamps, it returns an error message in parentheses.
func TimestampString(ts *tspb.Timestamp) string {
t, err := Timestamp(ts)
if err != nil {
return fmt.Sprintf("(%v)", err)
}
return t.Format(time.RFC3339Nano)
}

Просмотреть файл

@ -10,6 +10,7 @@ import (
"time"
"github.com/golang/protobuf/proto"
tspb "github.com/golang/protobuf/ptypes/timestamp"
)
@ -97,7 +98,6 @@ func TestTimestampString(t *testing.T) {
// Not much testing needed because presumably time.Format is
// well-tested.
{&tspb.Timestamp{Seconds: 0, Nanos: 0}, "1970-01-01T00:00:00Z"},
{&tspb.Timestamp{Seconds: minValidSeconds - 1, Nanos: 0}, "(timestamp: seconds:-62135596801 before 0001-01-01)"},
} {
got := TimestampString(test.ts)
if got != test.want {

Просмотреть файл

@ -10,18 +10,14 @@ PASS="\x1b[32mPASS"
FAIL="\x1b[31mFAIL"
RESET="\x1b[0m"
echo -e "${BOLD}go test -tags protolegacy ./...${RESET}"
RET_TEST0=$(go test -tags protolegacy ./... | egrep -v "^(ok|[?])\s+")
echo -e "${BOLD}go test ./...${RESET}"
RET_TEST0=$(go test ./... | egrep -v "^(ok|[?])\s+")
if [[ ! -z "$RET_TEST0" ]]; then echo "$RET_TEST0"; echo; fi
echo -e "${BOLD}go test -tags use_golang_protobuf_v1 ./...${RESET}"
RET_TEST1=$(go test -tags use_golang_protobuf_v1 ./... | egrep -v "^(ok|[?])\s+")
echo -e "${BOLD}go test -tags purego ./...${RESET}"
RET_TEST1=$(go test -tags purego ./... | egrep -v "^(ok|[?])\s+")
if [[ ! -z "$RET_TEST1" ]]; then echo "$RET_TEST1"; echo; fi
echo -e "${BOLD}go test -tags "use_golang_protobuf_v1 purego" ./...${RESET}"
RET_TEST2=$(go test -tags "use_golang_protobuf_v1 purego" ./... | egrep -v "^(ok|[?])\s+")
if [[ ! -z "$RET_TEST2" ]]; then echo "$RET_TEST2"; echo; fi
echo -e "${BOLD}go generate${RESET}"
RET_GEN=$(go run ./internal/cmd/generate-alias 2>&1)
if [[ ! -z "$RET_GEN" ]]; then echo "$RET_GEN"; echo; fi
@ -38,7 +34,7 @@ echo -e "${BOLD}git ls-files${RESET}"
RET_FILES=$(git ls-files --others --exclude-standard 2>&1)
if [[ ! -z "$RET_FILES" ]]; then echo "$RET_FILES"; echo; fi
if [[ ! -z "$RET_TEST0" ]] || [[ ! -z "$RET_TEST1" ]] || [[ ! -z "$RET_TEST2" ]] || [[ ! -z "$RET_GEN" ]] || [ ! -z "$RET_FMT" ] || [[ ! -z "$RET_DIFF" ]] || [[ ! -z "$RET_FILES" ]]; then
if [[ ! -z "$RET_TEST0" ]] || [[ ! -z "$RET_TEST1" ]] || [[ ! -z "$RET_GEN" ]] || [ ! -z "$RET_FMT" ] || [[ ! -z "$RET_DIFF" ]] || [[ ! -z "$RET_FILES" ]]; then
echo -e "${FAIL}${RESET}"; exit 1
else
echo -e "${PASS}${RESET}"; exit 0