diff options
author | David Symonds <dsymonds@golang.org> | 2013-03-23 17:20:01 +1100 |
---|---|---|
committer | David Symonds <dsymonds@golang.org> | 2013-03-23 17:20:01 +1100 |
commit | 2037090d1d590ec49ee92abd55a9434006b94bb2 (patch) | |
tree | b639c18e71d33f6b3e8f1b216ea568a0a550512f | |
parent | 22e7eb4717085235b29a5ae20e11b9bcd89f412f (diff) | |
download | protobuf-2037090d1d590ec49ee92abd55a9434006b94bb2.tar.gz |
goprotobuf: Match C++ for text format of unknown fields.
R=r
CC=golang-dev
https://codereview.appspot.com/7982043
-rw-r--r-- | proto/properties.go | 5 | ||||
-rw-r--r-- | proto/size_test.go | 1 | ||||
-rw-r--r-- | proto/testdata/test.proto | 16 | ||||
-rw-r--r-- | proto/text.go | 10 | ||||
-rw-r--r-- | proto/text_parser.go | 7 | ||||
-rw-r--r-- | proto/text_test.go | 6 |
6 files changed, 34 insertions, 11 deletions
diff --git a/proto/properties.go b/proto/properties.go index 72e6b21..28d4e1d 100644 --- a/proto/properties.go +++ b/proto/properties.go @@ -515,10 +515,13 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { prop.unrecField = invalidField prop.Prop = make([]*Properties, t.NumField()) prop.order = make([]int, t.NumField()) + for i := 0; i < t.NumField(); i++ { f := t.Field(i) p := new(Properties) - p.init(f.Type, f.Name, f.Tag.Get("protobuf"), &f, false) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + if f.Name == "XXX_extensions" { // special case p.enc = (*Buffer).enc_map p.dec = nil // not needed diff --git a/proto/size_test.go b/proto/size_test.go index 9c60e4f..ec35f52 100644 --- a/proto/size_test.go +++ b/proto/size_test.go @@ -54,6 +54,7 @@ func init() { // Force messageWithExtension3 to have the extension encoded. Marshal(messageWithExtension3) + } var SizeTests = []struct { diff --git a/proto/testdata/test.proto b/proto/testdata/test.proto index a7f38d4..1caffb4 100644 --- a/proto/testdata/test.proto +++ b/proto/testdata/test.proto @@ -334,3 +334,19 @@ message MoreRepeated { repeated int32 ints_packed = 4 [packed=true]; repeated string strings = 5; } + +// GroupOld and GroupNew have the same wire format. +// GroupNew has a new field inside a group. + +message GroupOld { + optional group G = 1 { + optional int32 x = 2; + } +} + +message GroupNew { + optional group G = 1 { + optional int32 x = 2; + optional int32 y = 3; + } +} diff --git a/proto/text.go b/proto/text.go index 64a4ae7..28a978e 100644 --- a/proto/text.go +++ b/proto/text.go @@ -183,8 +183,11 @@ func writeStruct(w *textWriter, sv reflect.Value) error { sprops := GetProperties(st) for i := 0; i < sv.NumField(); i++ { fv := sv.Field(i) - if name := st.Field(i).Name; strings.HasPrefix(name, "XXX_") { - // There's only two XXX_ fields: + props := sprops.Prop[i] + name := st.Field(i).Name + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: // XXX_unrecognized []byte // XXX_extensions map[int32]proto.Extension // The first is handled here; @@ -196,7 +199,6 @@ func writeStruct(w *textWriter, sv reflect.Value) error { } continue } - props := sprops.Prop[i] 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 @@ -464,7 +466,7 @@ func writeUnknownStruct(w *textWriter, data []byte) (err error) { } continue } - if _, err := fmt.Fprintf(w, "tag%d", tag); err != nil { + if _, err := fmt.Fprint(w, tag); err != nil { return err } if wire != WireStartGroup { diff --git a/proto/text_parser.go b/proto/text_parser.go index b4e4bc1..9bf8095 100644 --- a/proto/text_parser.go +++ b/proto/text_parser.go @@ -505,8 +505,11 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) *ParseError return p.errorf("unknown field name %q in %v", tok.value, st) } + dst := sv.Field(fi) + isDstNil := isNil(dst) + // Check that it's not already set if it's not a repeated field. - if !props.Repeated && !isNil(sv.Field(fi)) { + if !props.Repeated && !isDstNil { return p.errorf("non-repeated field %q was repeated", tok.value) } @@ -514,8 +517,6 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) *ParseError return err } - dst := sv.Field(fi) - // Parse into the field. if err := p.readAny(dst, props); err != nil { return err diff --git a/proto/text_test.go b/proto/text_test.go index 4904295..e6927a4 100644 --- a/proto/text_test.go +++ b/proto/text_test.go @@ -128,7 +128,7 @@ SomeGroup { group_field: 8 } /* 2 unknown bytes */ -tag13: 4 +13: 4 [testdata.Ext.more]: < data: "Big gobs for big rats" > @@ -136,9 +136,9 @@ tag13: 4 [testdata.greeting]: "easy" [testdata.greeting]: "cow" /* 13 unknown bytes */ -tag201: "\t3G skiing" +201: "\t3G skiing" /* 3 unknown bytes */ -tag202: 19 +202: 19 ` func TestMarshalText(t *testing.T) { |