mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-04-17 02:42:35 +00:00
encoding/textpb: add marshaling of unknown fields
Change-Id: Ifa2a86b3edd51d6c53d9cf7226b6f4f8d2f88a44 Reviewed-on: https://go-review.googlesource.com/c/153757 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
parent
800c990248
commit
20a1d31685
@ -5,9 +5,11 @@
|
||||
package textpb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/golang/protobuf/v2/internal/encoding/text"
|
||||
"github.com/golang/protobuf/v2/internal/encoding/wire"
|
||||
"github.com/golang/protobuf/v2/internal/errors"
|
||||
"github.com/golang/protobuf/v2/internal/pragma"
|
||||
"github.com/golang/protobuf/v2/proto"
|
||||
@ -106,10 +108,16 @@ func (o MarshalOptions) marshalMessage(m pref.Message) (text.Value, error) {
|
||||
}
|
||||
msgFields = append(msgFields, [2]text.Value{tname, tval})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Handle extensions, unknowns and Any.
|
||||
// Marshal out unknown fields.
|
||||
// TODO: Provide option to exclude or include unknown fields.
|
||||
m.UnknownFields().Range(func(_ pref.FieldNumber, raw pref.RawFields) bool {
|
||||
msgFields = appendUnknown(msgFields, raw)
|
||||
return true
|
||||
})
|
||||
|
||||
// TODO: Handle extensions and Any expansion.
|
||||
|
||||
return text.ValueOf(msgFields), nerr.E
|
||||
}
|
||||
@ -243,3 +251,35 @@ func sortMap(keyKind pref.Kind, values []text.Value) {
|
||||
}
|
||||
sort.Slice(values, less)
|
||||
}
|
||||
|
||||
// appendUnknown parses the given []byte and appends field(s) into the given fields slice.
|
||||
// This function assumes proper encoding in the given []byte.
|
||||
func appendUnknown(fields [][2]text.Value, b []byte) [][2]text.Value {
|
||||
for len(b) > 0 {
|
||||
var value interface{}
|
||||
num, wtype, n := wire.ConsumeTag(b)
|
||||
b = b[n:]
|
||||
|
||||
switch wtype {
|
||||
case wire.VarintType:
|
||||
value, n = wire.ConsumeVarint(b)
|
||||
case wire.Fixed32Type:
|
||||
value, n = wire.ConsumeFixed32(b)
|
||||
case wire.Fixed64Type:
|
||||
value, n = wire.ConsumeFixed64(b)
|
||||
case wire.BytesType:
|
||||
value, n = wire.ConsumeBytes(b)
|
||||
case wire.StartGroupType:
|
||||
var v []byte
|
||||
v, n = wire.ConsumeGroup(num, b)
|
||||
var msg [][2]text.Value
|
||||
value = appendUnknown(msg, v)
|
||||
default:
|
||||
panic(fmt.Sprintf("error parsing unknown field wire type: %v", wtype))
|
||||
}
|
||||
|
||||
fields = append(fields, [2]text.Value{text.ValueOf(uint32(num)), text.ValueOf(value)})
|
||||
b = b[n:]
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
protoV1 "github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/v2/encoding/textpb"
|
||||
"github.com/golang/protobuf/v2/internal/detrand"
|
||||
"github.com/golang/protobuf/v2/internal/encoding/pack"
|
||||
"github.com/golang/protobuf/v2/internal/impl"
|
||||
"github.com/golang/protobuf/v2/internal/scalar"
|
||||
"github.com/golang/protobuf/v2/proto"
|
||||
@ -737,6 +738,68 @@ req_nested: {}
|
||||
}
|
||||
`,
|
||||
wantErr: true,
|
||||
}, {
|
||||
desc: "unknown varint and fixed types",
|
||||
input: &pb2.Scalars{
|
||||
OptString: scalar.String("this message contains unknown fields"),
|
||||
XXX_unrecognized: pack.Message{
|
||||
pack.Tag{101, pack.VarintType}, pack.Bool(true),
|
||||
pack.Tag{102, pack.VarintType}, pack.Varint(0xff),
|
||||
pack.Tag{103, pack.Fixed32Type}, pack.Uint32(47),
|
||||
pack.Tag{104, pack.Fixed64Type}, pack.Int64(0xdeadbeef),
|
||||
}.Marshal(),
|
||||
},
|
||||
want: `opt_string: "this message contains unknown fields"
|
||||
101: 1
|
||||
102: 255
|
||||
103: 47
|
||||
104: 3735928559
|
||||
`,
|
||||
}, {
|
||||
desc: "unknown length-delimited",
|
||||
input: &pb2.Scalars{
|
||||
XXX_unrecognized: pack.Message{
|
||||
pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false)},
|
||||
pack.Tag{102, pack.BytesType}, pack.String("hello world"),
|
||||
pack.Tag{103, pack.BytesType}, pack.Bytes("\xe4\xb8\x96\xe7\x95\x8c"),
|
||||
}.Marshal(),
|
||||
},
|
||||
want: `101: "\x01\x00"
|
||||
102: "hello world"
|
||||
103: "世界"
|
||||
`,
|
||||
}, {
|
||||
desc: "unknown group type",
|
||||
input: &pb2.Scalars{
|
||||
XXX_unrecognized: pack.Message{
|
||||
pack.Tag{101, pack.StartGroupType}, pack.Tag{101, pack.EndGroupType},
|
||||
pack.Tag{102, pack.StartGroupType},
|
||||
pack.Tag{101, pack.VarintType}, pack.Bool(false),
|
||||
pack.Tag{102, pack.BytesType}, pack.String("inside a group"),
|
||||
pack.Tag{102, pack.EndGroupType},
|
||||
}.Marshal(),
|
||||
},
|
||||
want: `101: {}
|
||||
102: {
|
||||
101: 0
|
||||
102: "inside a group"
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
desc: "unknown unpack repeated field",
|
||||
input: &pb2.Scalars{
|
||||
XXX_unrecognized: pack.Message{
|
||||
pack.Tag{101, pack.BytesType}, pack.LengthPrefix{pack.Bool(true), pack.Bool(false), pack.Bool(true)},
|
||||
pack.Tag{102, pack.BytesType}, pack.String("hello"),
|
||||
pack.Tag{101, pack.VarintType}, pack.Bool(true),
|
||||
pack.Tag{102, pack.BytesType}, pack.String("世界"),
|
||||
}.Marshal(),
|
||||
},
|
||||
want: `101: "\x01\x00\x01"
|
||||
101: 1
|
||||
102: "hello"
|
||||
102: "世界"
|
||||
`,
|
||||
}}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
Loading…
x
Reference in New Issue
Block a user