internal/filedesc, internal/filetype: initial commit
The internal/fileinit package is split apart into two packages:
* internal/filedesc constructs descriptors from the raw proto.
It is very similar to the previous internal/fileinit package.
* internal/filetype wraps descriptors with Go type information
Overview:
* The internal/fileinit package will be deleted in a future CL.
It is kept around since the v1 repo currently depends on it.
* The internal/prototype package is deleted. All former usages of it
are now using internal/filedesc instead. Most significantly,
the reflect/protodesc package was almost entirely re-written.
* The internal/impl package drops support for messages that do not
have a Descriptor method (pre-2016). This removes a significant amount
of technical debt.
filedesc.Builder to parse raw descriptors.
* The internal/encoding/defval package now handles enum values by name.
Change-Id: I3957bcc8588a70470fd6c7de1122216b80615ab7
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/182360
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/encoding/defval/default.go b/internal/encoding/defval/default.go
index a15df02..f03acdf 100644
--- a/internal/encoding/defval/default.go
+++ b/internal/encoding/defval/default.go
@@ -34,54 +34,55 @@
)
// Unmarshal deserializes the default string s according to the given kind k.
-// When using the Descriptor format on an enum kind, a Value of type string
-// representing the enum identifier is returned. It is the caller's
-// responsibility to verify that the identifier is valid.
-func Unmarshal(s string, k pref.Kind, f Format) (pref.Value, error) {
+// When k is an enum, a list of enum value descriptors must be provided.
+func Unmarshal(s string, k pref.Kind, evs pref.EnumValueDescriptors, f Format) (pref.Value, pref.EnumValueDescriptor, error) {
switch k {
case pref.BoolKind:
if f == GoTag {
switch s {
case "1":
- return pref.ValueOf(true), nil
+ return pref.ValueOf(true), nil, nil
case "0":
- return pref.ValueOf(false), nil
+ return pref.ValueOf(false), nil, nil
}
} else {
switch s {
case "true":
- return pref.ValueOf(true), nil
+ return pref.ValueOf(true), nil, nil
case "false":
- return pref.ValueOf(false), nil
+ return pref.ValueOf(false), nil, nil
}
}
case pref.EnumKind:
if f == GoTag {
- // Go tags used the numeric form of the enum value.
+ // Go tags use the numeric form of the enum value.
if n, err := strconv.ParseInt(s, 10, 32); err == nil {
- return pref.ValueOf(pref.EnumNumber(n)), nil
+ if ev := evs.ByNumber(pref.EnumNumber(n)); ev != nil {
+ return pref.ValueOf(ev.Number()), ev, nil
+ }
}
} else {
- // Descriptor default_value used the enum identifier.
- if pref.Name(s).IsValid() {
- return pref.ValueOf(s), nil
+ // Descriptor default_value use the enum identifier.
+ ev := evs.ByName(pref.Name(s))
+ if ev != nil {
+ return pref.ValueOf(ev.Number()), ev, nil
}
}
case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
if v, err := strconv.ParseInt(s, 10, 32); err == nil {
- return pref.ValueOf(int32(v)), nil
+ return pref.ValueOf(int32(v)), nil, nil
}
case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
if v, err := strconv.ParseInt(s, 10, 64); err == nil {
- return pref.ValueOf(int64(v)), nil
+ return pref.ValueOf(int64(v)), nil, nil
}
case pref.Uint32Kind, pref.Fixed32Kind:
if v, err := strconv.ParseUint(s, 10, 32); err == nil {
- return pref.ValueOf(uint32(v)), nil
+ return pref.ValueOf(uint32(v)), nil, nil
}
case pref.Uint64Kind, pref.Fixed64Kind:
if v, err := strconv.ParseUint(s, 10, 64); err == nil {
- return pref.ValueOf(uint64(v)), nil
+ return pref.ValueOf(uint64(v)), nil, nil
}
case pref.FloatKind, pref.DoubleKind:
var v float64
@@ -98,25 +99,26 @@
}
if err == nil {
if k == pref.FloatKind {
- return pref.ValueOf(float32(v)), nil
+ return pref.ValueOf(float32(v)), nil, nil
} else {
- return pref.ValueOf(float64(v)), nil
+ return pref.ValueOf(float64(v)), nil, nil
}
}
case pref.StringKind:
// String values are already unescaped and can be used as is.
- return pref.ValueOf(s), nil
+ return pref.ValueOf(s), nil, nil
case pref.BytesKind:
if b, ok := unmarshalBytes(s); ok {
- return pref.ValueOf(b), nil
+ return pref.ValueOf(b), nil, nil
}
}
- return pref.Value{}, errors.New("invalid default value for %v: %q", k, s)
+ return pref.Value{}, nil, errors.New("invalid default value for %v: %q", k, s)
}
// Marshal serializes v as the default string according to the given kind k.
-// Enums are serialized in numeric form regardless of format chosen.
-func Marshal(v pref.Value, k pref.Kind, f Format) (string, error) {
+// When specifying the Descriptor format for an enum kind, the associated
+// enum value descriptor must be provided.
+func Marshal(v pref.Value, ev pref.EnumValueDescriptor, k pref.Kind, f Format) (string, error) {
switch k {
case pref.BoolKind:
if f == GoTag {
@@ -133,7 +135,11 @@
}
}
case pref.EnumKind:
- return strconv.FormatInt(int64(v.Enum()), 10), nil
+ if f == GoTag {
+ return strconv.FormatInt(int64(v.Enum()), 10), nil
+ } else {
+ return string(ev.Name()), nil
+ }
case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
return strconv.FormatInt(v.Int(), 10), nil
case pref.Uint32Kind, pref.Fixed32Kind, pref.Uint64Kind, pref.Fixed64Kind:
diff --git a/internal/encoding/defval/default_test.go b/internal/encoding/defval/default_test.go
index a25a93f..d81150d 100644
--- a/internal/encoding/defval/default_test.go
+++ b/internal/encoding/defval/default_test.go
@@ -2,52 +2,103 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package defval
+package defval_test
import (
"math"
"reflect"
"testing"
+ "google.golang.org/protobuf/internal/encoding/defval"
+ fdesc "google.golang.org/protobuf/internal/filedesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
func Test(t *testing.T) {
+ evs := fdesc.EnumValues{List: []fdesc.EnumValue{{}}}
+ evs.List[0].L0.ParentFile = fdesc.SurrogateProto2
+ evs.List[0].L0.FullName = "ALPHA"
+ evs.List[0].L1.Number = 1
+
V := pref.ValueOf
tests := []struct {
val pref.Value
+ enum pref.EnumValueDescriptor
+ enums pref.EnumValueDescriptors
kind pref.Kind
strPB string
strGo string
- }{
- {V(bool(true)), pref.BoolKind, "true", "1"},
- {V(int32(-0x1234)), pref.Int32Kind, "-4660", "-4660"},
- {V(float32(math.Pi)), pref.FloatKind, "3.1415927", "3.1415927"},
- {V(float64(math.Pi)), pref.DoubleKind, "3.141592653589793", "3.141592653589793"},
- {V(string("hello, \xde\xad\xbe\xef\n")), pref.StringKind, "hello, \xde\xad\xbe\xef\n", "hello, \xde\xad\xbe\xef\n"},
- {V([]byte("hello, \xde\xad\xbe\xef\n")), pref.BytesKind, "hello, \\336\\255\\276\\357\\n", "hello, \\336\\255\\276\\357\\n"},
- }
+ }{{
+ val: V(bool(true)),
+ enum: nil,
+ enums: nil,
+ kind: pref.BoolKind,
+ strPB: "true",
+ strGo: "1",
+ }, {
+ val: V(int32(-0x1234)),
+ enum: nil,
+ enums: nil,
+ kind: pref.Int32Kind,
+ strPB: "-4660",
+ strGo: "-4660",
+ }, {
+ val: V(float32(math.Pi)),
+ enum: nil,
+ enums: nil,
+ kind: pref.FloatKind,
+ strPB: "3.1415927",
+ strGo: "3.1415927",
+ }, {
+ val: V(float64(math.Pi)),
+ enum: nil,
+ enums: nil,
+ kind: pref.DoubleKind,
+ strPB: "3.141592653589793",
+ strGo: "3.141592653589793",
+ }, {
+ val: V(string("hello, \xde\xad\xbe\xef\n")),
+ enum: nil,
+ enums: nil,
+ kind: pref.StringKind,
+ strPB: "hello, \xde\xad\xbe\xef\n",
+ strGo: "hello, \xde\xad\xbe\xef\n",
+ }, {
+ val: V([]byte("hello, \xde\xad\xbe\xef\n")),
+ enum: nil,
+ enums: nil,
+ kind: pref.BytesKind,
+ strPB: "hello, \\336\\255\\276\\357\\n",
+ strGo: "hello, \\336\\255\\276\\357\\n",
+ }, {
+ val: V(pref.EnumNumber(1)),
+ enum: &evs.List[0],
+ enums: &evs,
+ kind: pref.EnumKind,
+ strPB: "ALPHA",
+ strGo: "1",
+ }}
for _, tt := range tests {
t.Run("", func(t *testing.T) {
- gotStrPB, _ := Marshal(tt.val, tt.kind, Descriptor)
- if gotStrPB != tt.strPB {
- t.Errorf("Marshal(%v, %v, Descriptor) = %q, want %q", tt.val, tt.kind, gotStrPB, tt.strPB)
+ gotStr, _ := defval.Marshal(tt.val, tt.enum, tt.kind, defval.Descriptor)
+ if gotStr != tt.strPB {
+ t.Errorf("Marshal(%v, %v, Descriptor) = %q, want %q", tt.val, tt.kind, gotStr, tt.strPB)
}
- gotStrGo, _ := Marshal(tt.val, tt.kind, GoTag)
- if gotStrGo != tt.strGo {
- t.Errorf("Marshal(%v, %v, GoTag) = %q, want %q", tt.val, tt.kind, gotStrGo, tt.strGo)
+ gotStr, _ = defval.Marshal(tt.val, tt.enum, tt.kind, defval.GoTag)
+ if gotStr != tt.strGo {
+ t.Errorf("Marshal(%v, %v, GoTag) = %q, want %q", tt.val, tt.kind, gotStr, tt.strGo)
}
- gotValPB, _ := Unmarshal(tt.strPB, tt.kind, Descriptor)
- if !reflect.DeepEqual(gotValPB.Interface(), tt.val.Interface()) {
- t.Errorf("Unmarshal(%v, %v, Descriptor) = %q, want %q", tt.strPB, tt.kind, gotValPB, tt.val)
+ gotVal, gotEnum, _ := defval.Unmarshal(tt.strPB, tt.kind, tt.enums, defval.Descriptor)
+ if !reflect.DeepEqual(gotVal.Interface(), tt.val.Interface()) || gotEnum != tt.enum {
+ t.Errorf("Unmarshal(%v, %v, Descriptor) = (%q, %v), want (%q, %v)", tt.strPB, tt.kind, gotVal, gotEnum, tt.val, tt.enum)
}
- gotValGo, _ := Unmarshal(tt.strGo, tt.kind, GoTag)
- if !reflect.DeepEqual(gotValGo.Interface(), tt.val.Interface()) {
- t.Errorf("Unmarshal(%v, %v, GoTag) = %q, want %q", tt.strGo, tt.kind, gotValGo, tt.val)
+ gotVal, gotEnum, _ = defval.Unmarshal(tt.strGo, tt.kind, tt.enums, defval.GoTag)
+ if !reflect.DeepEqual(gotVal.Interface(), tt.val.Interface()) || gotEnum != tt.enum {
+ t.Errorf("Unmarshal(%v, %v, GoTag) = (%q, %v), want (%q, %v)", tt.strGo, tt.kind, gotVal, gotEnum, tt.val, tt.enum)
}
})
}
diff --git a/internal/encoding/pack/pack_test.go b/internal/encoding/pack/pack_test.go
index d2f8baa..d6704e9 100644
--- a/internal/encoding/pack/pack_test.go
+++ b/internal/encoding/pack/pack_test.go
@@ -11,35 +11,47 @@
"math"
"testing"
- cmp "github.com/google/go-cmp/cmp"
- ptype "google.golang.org/protobuf/internal/prototype"
+ "github.com/google/go-cmp/cmp"
+ "google.golang.org/protobuf/encoding/prototext"
+ pdesc "google.golang.org/protobuf/reflect/protodesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
+
+ "google.golang.org/protobuf/types/descriptorpb"
)
var msgDesc = func() pref.MessageDescriptor {
- mtyp, err := ptype.NewMessage(&ptype.StandaloneMessage{
- Syntax: pref.Proto2,
- FullName: "Message",
- Fields: []ptype.Field{
- {Name: "F1", Number: 1, Cardinality: pref.Repeated, Kind: pref.BoolKind, IsPacked: ptype.True},
- {Name: "F2", Number: 2, Cardinality: pref.Repeated, Kind: pref.Int64Kind, IsPacked: ptype.True},
- {Name: "F3", Number: 3, Cardinality: pref.Repeated, Kind: pref.Sint64Kind, IsPacked: ptype.True},
- {Name: "F4", Number: 4, Cardinality: pref.Repeated, Kind: pref.Uint64Kind, IsPacked: ptype.True},
- {Name: "F5", Number: 5, Cardinality: pref.Repeated, Kind: pref.Fixed32Kind, IsPacked: ptype.True},
- {Name: "F6", Number: 6, Cardinality: pref.Repeated, Kind: pref.Sfixed32Kind, IsPacked: ptype.True},
- {Name: "F7", Number: 7, Cardinality: pref.Repeated, Kind: pref.FloatKind, IsPacked: ptype.True},
- {Name: "F8", Number: 8, Cardinality: pref.Repeated, Kind: pref.Fixed64Kind, IsPacked: ptype.True},
- {Name: "F9", Number: 9, Cardinality: pref.Repeated, Kind: pref.Sfixed64Kind, IsPacked: ptype.True},
- {Name: "F10", Number: 10, Cardinality: pref.Repeated, Kind: pref.DoubleKind, IsPacked: ptype.True},
- {Name: "F11", Number: 11, Cardinality: pref.Optional, Kind: pref.StringKind},
- {Name: "F12", Number: 12, Cardinality: pref.Optional, Kind: pref.BytesKind},
- {Name: "F13", Number: 13, Cardinality: pref.Optional, Kind: pref.MessageKind, MessageType: ptype.PlaceholderMessage("Message")},
- {Name: "F14", Number: 14, Cardinality: pref.Optional, Kind: pref.GroupKind, MessageType: ptype.PlaceholderMessage("Message")}},
- })
+ const s = `
+ name: "test.proto"
+ syntax: "proto2"
+ message_type: [{
+ name: "Message"
+ field: [
+ {name:"F1" number:1 label:LABEL_REPEATED type:TYPE_BOOL options:{packed:true}},
+ {name:"F2" number:2 label:LABEL_REPEATED type:TYPE_INT64 options:{packed:true}},
+ {name:"F3" number:3 label:LABEL_REPEATED type:TYPE_SINT64 options:{packed:true}},
+ {name:"F4" number:4 label:LABEL_REPEATED type:TYPE_UINT64 options:{packed:true}},
+ {name:"F5" number:5 label:LABEL_REPEATED type:TYPE_FIXED32 options:{packed:true}},
+ {name:"F6" number:6 label:LABEL_REPEATED type:TYPE_SFIXED32 options:{packed:true}},
+ {name:"F7" number:7 label:LABEL_REPEATED type:TYPE_FLOAT options:{packed:true}},
+ {name:"F8" number:8 label:LABEL_REPEATED type:TYPE_FIXED64 options:{packed:true}},
+ {name:"F9" number:9 label:LABEL_REPEATED type:TYPE_SFIXED64 options:{packed:true}},
+ {name:"F10" number:10 label:LABEL_REPEATED type:TYPE_DOUBLE options:{packed:true}},
+ {name:"F11" number:11 label:LABEL_OPTIONAL type:TYPE_STRING},
+ {name:"F12" number:12 label:LABEL_OPTIONAL type:TYPE_BYTES},
+ {name:"F13" number:13 label:LABEL_OPTIONAL type:TYPE_MESSAGE type_name:".Message"},
+ {name:"F14" number:14 label:LABEL_OPTIONAL type:TYPE_GROUP type_name:".Message"}
+ ]
+ }]
+ `
+ pb := new(descriptorpb.FileDescriptorProto)
+ if err := prototext.Unmarshal([]byte(s), pb); err != nil {
+ panic(err)
+ }
+ fd, err := pdesc.NewFile(pb, nil)
if err != nil {
panic(err)
}
- return mtyp
+ return fd.Messages().Get(0)
}()
// dhex decodes a hex-string and returns the bytes and panics if s is invalid.
diff --git a/internal/encoding/tag/tag.go b/internal/encoding/tag/tag.go
index f1f24e8..1c568e3 100644
--- a/internal/encoding/tag/tag.go
+++ b/internal/encoding/tag/tag.go
@@ -12,7 +12,7 @@
"strings"
defval "google.golang.org/protobuf/internal/encoding/defval"
- ptype "google.golang.org/protobuf/internal/prototype"
+ fdesc "google.golang.org/protobuf/internal/filedesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
@@ -24,11 +24,13 @@
// tag does not record sufficient information to determine that.
// The type is the underlying field type (e.g., a repeated field may be
// represented by []T, but the Go type passed in is just T).
-// This does not populate the EnumType or MessageType (except for weak message).
+// A list of enum value descriptors must be provided for enum fields.
+// This does not populate the Enum or Message (except for weak message).
//
// This function is a best effort attempt; parsing errors are ignored.
-func Unmarshal(tag string, goType reflect.Type) ptype.Field {
- f := ptype.Field{}
+func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor {
+ f := new(fdesc.Field)
+ f.L0.ParentFile = fdesc.SurrogateProto2
for len(tag) > 0 {
i := strings.IndexByte(tag, ',')
if i < 0 {
@@ -36,88 +38,92 @@
}
switch s := tag[:i]; {
case strings.HasPrefix(s, "name="):
- f.Name = pref.Name(s[len("name="):])
+ f.L0.FullName = pref.FullName(s[len("name="):])
case strings.Trim(s, "0123456789") == "":
n, _ := strconv.ParseUint(s, 10, 32)
- f.Number = pref.FieldNumber(n)
+ f.L1.Number = pref.FieldNumber(n)
case s == "opt":
- f.Cardinality = pref.Optional
+ f.L1.Cardinality = pref.Optional
case s == "req":
- f.Cardinality = pref.Required
+ f.L1.Cardinality = pref.Required
case s == "rep":
- f.Cardinality = pref.Repeated
+ f.L1.Cardinality = pref.Repeated
case s == "varint":
switch goType.Kind() {
case reflect.Bool:
- f.Kind = pref.BoolKind
+ f.L1.Kind = pref.BoolKind
case reflect.Int32:
- f.Kind = pref.Int32Kind
+ f.L1.Kind = pref.Int32Kind
case reflect.Int64:
- f.Kind = pref.Int64Kind
+ f.L1.Kind = pref.Int64Kind
case reflect.Uint32:
- f.Kind = pref.Uint32Kind
+ f.L1.Kind = pref.Uint32Kind
case reflect.Uint64:
- f.Kind = pref.Uint64Kind
+ f.L1.Kind = pref.Uint64Kind
}
case s == "zigzag32":
if goType.Kind() == reflect.Int32 {
- f.Kind = pref.Sint32Kind
+ f.L1.Kind = pref.Sint32Kind
}
case s == "zigzag64":
if goType.Kind() == reflect.Int64 {
- f.Kind = pref.Sint64Kind
+ f.L1.Kind = pref.Sint64Kind
}
case s == "fixed32":
switch goType.Kind() {
case reflect.Int32:
- f.Kind = pref.Sfixed32Kind
+ f.L1.Kind = pref.Sfixed32Kind
case reflect.Uint32:
- f.Kind = pref.Fixed32Kind
+ f.L1.Kind = pref.Fixed32Kind
case reflect.Float32:
- f.Kind = pref.FloatKind
+ f.L1.Kind = pref.FloatKind
}
case s == "fixed64":
switch goType.Kind() {
case reflect.Int64:
- f.Kind = pref.Sfixed64Kind
+ f.L1.Kind = pref.Sfixed64Kind
case reflect.Uint64:
- f.Kind = pref.Fixed64Kind
+ f.L1.Kind = pref.Fixed64Kind
case reflect.Float64:
- f.Kind = pref.DoubleKind
+ f.L1.Kind = pref.DoubleKind
}
case s == "bytes":
switch {
case goType.Kind() == reflect.String:
- f.Kind = pref.StringKind
+ f.L1.Kind = pref.StringKind
case goType.Kind() == reflect.Slice && goType.Elem() == byteType:
- f.Kind = pref.BytesKind
+ f.L1.Kind = pref.BytesKind
default:
- f.Kind = pref.MessageKind
+ f.L1.Kind = pref.MessageKind
}
case s == "group":
- f.Kind = pref.GroupKind
+ f.L1.Kind = pref.GroupKind
case strings.HasPrefix(s, "enum="):
- f.Kind = pref.EnumKind
+ f.L1.Kind = pref.EnumKind
case strings.HasPrefix(s, "json="):
- f.JSONName = s[len("json="):]
+ f.L1.JSONName = fdesc.JSONName(s[len("json="):])
case s == "packed":
- f.IsPacked = ptype.True
+ f.L1.HasPacked = true
+ f.L1.IsPacked = true
case strings.HasPrefix(s, "weak="):
- f.IsWeak = true
- f.MessageType = ptype.PlaceholderMessage(pref.FullName(s[len("weak="):]))
+ f.L1.IsWeak = true
+ f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):]))
case strings.HasPrefix(s, "def="):
// The default tag is special in that everything afterwards is the
// default regardless of the presence of commas.
s, i = tag[len("def="):], len(tag)
- f.Default, _ = defval.Unmarshal(s, f.Kind, defval.GoTag)
+ v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag)
+ f.L1.Default = fdesc.DefaultValue(v, ev)
+ case s == "proto3":
+ f.L0.ParentFile = fdesc.SurrogateProto3
}
tag = strings.TrimPrefix(tag[i:], ",")
}
// The generator uses the group message name instead of the field name.
// We obtain the real field name by lowercasing the group name.
- if f.Kind == pref.GroupKind {
- f.Name = pref.Name(strings.ToLower(string(f.Name)))
+ if f.L1.Kind == pref.GroupKind {
+ f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName)))
}
return f
}
@@ -169,7 +175,8 @@
name = string(fd.Message().Name())
}
tag = append(tag, "name="+name)
- if jsonName := fd.JSONName(); jsonName != "" && jsonName != name {
+ if jsonName := fd.JSONName(); jsonName != "" && jsonName != name && !fd.IsExtension() {
+ // TODO: The jsonName != name condition looks wrong.
tag = append(tag, "json="+jsonName)
}
// The previous implementation does not tag extension fields as proto3,
@@ -186,7 +193,7 @@
}
// This must appear last in the tag, since commas in strings aren't escaped.
if fd.HasDefault() {
- def, _ := defval.Marshal(fd.Default(), fd.Kind(), defval.GoTag)
+ def, _ := defval.Marshal(fd.Default(), fd.DefaultEnumValue(), fd.Kind(), defval.GoTag)
tag = append(tag, "def="+def)
}
return strings.Join(tag, ",")
diff --git a/internal/encoding/tag/tag_test.go b/internal/encoding/tag/tag_test.go
index 0433b42..680ba52 100644
--- a/internal/encoding/tag/tag_test.go
+++ b/internal/encoding/tag/tag_test.go
@@ -2,54 +2,40 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package tag
+package tag_test
import (
"reflect"
"testing"
- "github.com/google/go-cmp/cmp"
- "github.com/google/go-cmp/cmp/cmpopts"
- ptype "google.golang.org/protobuf/internal/prototype"
+ "google.golang.org/protobuf/internal/encoding/tag"
+ fdesc "google.golang.org/protobuf/internal/filedesc"
+ "google.golang.org/protobuf/proto"
+ pdesc "google.golang.org/protobuf/reflect/protodesc"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
func Test(t *testing.T) {
- m := &ptype.StandaloneMessage{
- Syntax: pref.Proto3,
- FullName: "golang.org.example.FooMessage",
- Fields: []ptype.Field{{
- Name: "foo_field",
- Number: 1337,
- Cardinality: pref.Repeated,
- Kind: pref.BytesKind,
- JSONName: "fooField",
- Default: pref.ValueOf([]byte("hello, \xde\xad\xbe\xef\n")),
- }},
- }
- md, err := ptype.NewMessage(m)
- if err != nil {
- t.Fatalf("unexpected NewMessage error: %v", err)
- }
+ fd := new(fdesc.Field)
+ fd.L0.ParentFile = fdesc.SurrogateProto3
+ fd.L0.FullName = "foo_field"
+ fd.L1.Number = 1337
+ fd.L1.Cardinality = pref.Repeated
+ fd.L1.Kind = pref.BytesKind
+ fd.L1.JSONName = fdesc.JSONName("fooField")
+ fd.L1.Default = fdesc.DefaultValue(pref.ValueOf([]byte("hello, \xde\xad\xbe\xef\n")), nil)
// Marshal test.
- gotTag := Marshal(md.Fields().Get(0), "")
+ gotTag := tag.Marshal(fd, "")
wantTag := `bytes,1337,rep,name=foo_field,json=fooField,proto3,def=hello, \336\255\276\357\n`
if gotTag != wantTag {
t.Errorf("Marshal() = `%v`, want `%v`", gotTag, wantTag)
}
// Unmarshal test.
- gotField := Unmarshal(wantTag, reflect.TypeOf([]byte{}))
- wantField := m.Fields[0]
- opts := cmp.Options{
- cmp.Transformer("UnwrapValue", func(x pref.Value) interface{} {
- return x.Interface()
- }),
- cmpopts.IgnoreUnexported(ptype.Field{}),
- cmpopts.IgnoreFields(ptype.Field{}, "Options"),
- }
- if diff := cmp.Diff(wantField, gotField, opts); diff != "" {
- t.Errorf("Unmarshal() mismatch (-want +got):\n%v", diff)
+ gotFD := tag.Unmarshal(wantTag, reflect.TypeOf([]byte{}), nil)
+ wantFD := fd
+ if !proto.Equal(pdesc.ToFieldDescriptorProto(gotFD), pdesc.ToFieldDescriptorProto(wantFD)) {
+ t.Errorf("Umarshal() mismatch:\ngot %v\nwant %v", gotFD, wantFD)
}
}