blob: 731ee64d5eaa78ba94ae7bbce7525cf7243a219e [file] [log] [blame]
Herbie Ong800c9902018-12-06 15:28:53 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package textpb
6
7import (
8 "fmt"
Herbie Ong0dcfb9a2019-01-14 15:32:26 -08009 "strings"
Herbie Ong800c9902018-12-06 15:28:53 -080010
11 "github.com/golang/protobuf/v2/internal/encoding/text"
12 "github.com/golang/protobuf/v2/internal/errors"
Herbie Onge1e34932019-03-29 01:05:57 -070013 "github.com/golang/protobuf/v2/internal/fieldnum"
Herbie Ong800c9902018-12-06 15:28:53 -080014 "github.com/golang/protobuf/v2/internal/pragma"
15 "github.com/golang/protobuf/v2/internal/set"
16 "github.com/golang/protobuf/v2/proto"
17 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Ongc525c972018-12-18 18:04:31 -080018 "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080019)
20
21// Unmarshal reads the given []byte into the given proto.Message.
Herbie Ong800c9902018-12-06 15:28:53 -080022func Unmarshal(m proto.Message, b []byte) error {
23 return UnmarshalOptions{}.Unmarshal(m, b)
24}
25
Herbie Ong42577ea2019-03-26 16:26:22 -070026// UnmarshalOptions is a configurable textproto format unmarshaler.
Herbie Ong800c9902018-12-06 15:28:53 -080027type UnmarshalOptions struct {
28 pragma.NoUnkeyedLiterals
Herbie Ongc525c972018-12-18 18:04:31 -080029
Herbie Ong42577ea2019-03-26 16:26:22 -070030 // AllowPartial accepts input for messages that will result in missing
31 // required fields. If AllowPartial is false (the default), Unmarshal will
32 // return error if there are any missing required fields.
33 AllowPartial bool
34
Herbie Ongc525c972018-12-18 18:04:31 -080035 // Resolver is the registry used for type lookups when unmarshaling extensions
36 // and processing Any. If Resolver is not set, unmarshaling will default to
37 // using protoregistry.GlobalTypes.
38 Resolver *protoregistry.Types
Herbie Ong800c9902018-12-06 15:28:53 -080039}
40
41// Unmarshal reads the given []byte and populates the given proto.Message using options in
42// UnmarshalOptions object.
43func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
44 var nerr errors.NonFatal
45
46 mr := m.ProtoReflect()
47 // Clear all fields before populating it.
48 // TODO: Determine if this needs to be consistent with jsonpb and binary unmarshal where
49 // behavior is to merge values into existing message. If decision is to not clear the fields
50 // ahead, code will need to be updated properly when merging nested messages.
51 resetMessage(mr)
52
53 // Parse into text.Value of message type.
54 val, err := text.Unmarshal(b)
55 if !nerr.Merge(err) {
56 return err
57 }
58
Herbie Ongc525c972018-12-18 18:04:31 -080059 if o.Resolver == nil {
60 o.Resolver = protoregistry.GlobalTypes
61 }
Herbie Ong800c9902018-12-06 15:28:53 -080062 err = o.unmarshalMessage(val.Message(), mr)
63 if !nerr.Merge(err) {
64 return err
65 }
66
67 return nerr.E
68}
69
70// resetMessage clears all fields of given protoreflect.Message.
71// TODO: This should go into the proto package.
72func resetMessage(m pref.Message) {
73 knownFields := m.KnownFields()
74 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
75 knownFields.Clear(num)
76 return true
77 })
78 unknownFields := m.UnknownFields()
79 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
80 unknownFields.Set(num, nil)
81 return true
82 })
Herbie Ong800c9902018-12-06 15:28:53 -080083 extTypes := knownFields.ExtensionTypes()
84 extTypes.Range(func(xt pref.ExtensionType) bool {
85 extTypes.Remove(xt)
86 return true
87 })
88}
89
90// unmarshalMessage unmarshals a [][2]text.Value message into the given protoreflect.Message.
91func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message) error {
92 var nerr errors.NonFatal
93
94 msgType := m.Type()
Herbie Ong66c365c2019-01-04 14:08:41 -080095 knownFields := m.KnownFields()
96
97 // Handle expanded Any message.
98 if msgType.FullName() == "google.protobuf.Any" && isExpandedAny(tmsg) {
99 return o.unmarshalAny(tmsg[0], knownFields)
100 }
101
Herbie Ong800c9902018-12-06 15:28:53 -0800102 fieldDescs := msgType.Fields()
Herbie Ong7c624e22018-12-13 14:41:22 -0800103 reservedNames := msgType.ReservedNames()
Herbie Ongc525c972018-12-18 18:04:31 -0800104 xtTypes := knownFields.ExtensionTypes()
Herbie Ong800c9902018-12-06 15:28:53 -0800105 var reqNums set.Ints
106 var seenNums set.Ints
Herbie Ong8a1d4602019-04-02 20:19:36 -0700107 var seenOneofs set.Ints
Herbie Ong800c9902018-12-06 15:28:53 -0800108
109 for _, tfield := range tmsg {
110 tkey := tfield[0]
111 tval := tfield[1]
112
113 var fd pref.FieldDescriptor
Herbie Ongc525c972018-12-18 18:04:31 -0800114 var name pref.Name
115 switch tkey.Type() {
116 case text.Name:
117 name, _ = tkey.Name()
Herbie Ong800c9902018-12-06 15:28:53 -0800118 fd = fieldDescs.ByName(name)
Herbie Ong0dcfb9a2019-01-14 15:32:26 -0800119 if fd == nil {
120 // Check if this is a group field.
121 fd = fieldDescs.ByName(pref.Name(strings.ToLower(string(name))))
122 }
Herbie Ongc525c972018-12-18 18:04:31 -0800123 case text.String:
Herbie Ong66c365c2019-01-04 14:08:41 -0800124 // Handle extensions only. This code path is not for Any.
125 if msgType.FullName() == "google.protobuf.Any" {
126 break
127 }
128 // Extensions have to be registered first in the message's
Herbie Ongc525c972018-12-18 18:04:31 -0800129 // ExtensionTypes before setting a value to it.
130 xtName := pref.FullName(tkey.String())
Herbie Ong66c365c2019-01-04 14:08:41 -0800131 // Check first if it is already registered. This is the case for
132 // repeated fields.
Herbie Ongc525c972018-12-18 18:04:31 -0800133 xt := xtTypes.ByName(xtName)
134 if xt == nil {
135 var err error
Herbie Ong6470ea62019-01-07 18:56:57 -0800136 xt, err = o.findExtension(xtName)
Herbie Ongc525c972018-12-18 18:04:31 -0800137 if err != nil && err != protoregistry.NotFound {
Herbie Ong66c365c2019-01-04 14:08:41 -0800138 return errors.New("unable to resolve [%v]: %v", xtName, err)
Herbie Ongc525c972018-12-18 18:04:31 -0800139 }
140 if xt != nil {
141 xtTypes.Register(xt)
142 }
143 }
144 fd = xt
Herbie Ong800c9902018-12-06 15:28:53 -0800145 }
Herbie Ongc525c972018-12-18 18:04:31 -0800146
Herbie Ong800c9902018-12-06 15:28:53 -0800147 if fd == nil {
Herbie Ong7c624e22018-12-13 14:41:22 -0800148 // Ignore reserved names.
149 if reservedNames.Has(name) {
150 continue
151 }
Herbie Ong800c9902018-12-06 15:28:53 -0800152 // TODO: Can provide option to ignore unknown message fields.
Herbie Ong800c9902018-12-06 15:28:53 -0800153 return errors.New("%v contains unknown field: %v", msgType.FullName(), tkey)
154 }
155
156 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
157 // Map or list fields have cardinality of repeated.
158 if err := o.unmarshalRepeated(tval, fd, knownFields); !nerr.Merge(err) {
159 return err
160 }
161 } else {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700162 // If field is a oneof, check if it has already been set.
163 if od := fd.OneofType(); od != nil {
164 idx := uint64(od.Index())
165 if seenOneofs.Has(idx) {
166 return errors.New("oneof %v is already set", od.FullName())
167 }
168 seenOneofs.Set(idx)
169 }
170
Herbie Ong800c9902018-12-06 15:28:53 -0800171 // Required or optional fields.
172 num := uint64(fd.Number())
173 if seenNums.Has(num) {
174 return errors.New("non-repeated field %v is repeated", fd.FullName())
175 }
176 if err := o.unmarshalSingular(tval, fd, knownFields); !nerr.Merge(err) {
177 return err
178 }
Herbie Ong42577ea2019-03-26 16:26:22 -0700179 if !o.AllowPartial && cardinality == pref.Required {
Herbie Ong800c9902018-12-06 15:28:53 -0800180 reqNums.Set(num)
181 }
182 seenNums.Set(num)
183 }
184 }
185
Herbie Ong42577ea2019-03-26 16:26:22 -0700186 if !o.AllowPartial {
187 // Check for any missing required fields.
188 allReqNums := msgType.RequiredNumbers()
189 if reqNums.Len() != allReqNums.Len() {
190 for i := 0; i < allReqNums.Len(); i++ {
191 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
192 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
193 }
Herbie Ong800c9902018-12-06 15:28:53 -0800194 }
195 }
196 }
197
198 return nerr.E
199}
200
Herbie Ong6470ea62019-01-07 18:56:57 -0800201// findExtension returns protoreflect.ExtensionType from the Resolver if found.
202func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
203 xt, err := o.Resolver.FindExtensionByName(xtName)
204 if err == nil {
205 return xt, nil
206 }
207
208 // Check if this is a MessageSet extension field.
209 xt, err = o.Resolver.FindExtensionByName(xtName + ".message_set_extension")
210 if err == nil && isMessageSetExtension(xt) {
211 return xt, nil
212 }
213 return nil, protoregistry.NotFound
214}
215
Herbie Ong800c9902018-12-06 15:28:53 -0800216// unmarshalSingular unmarshals given text.Value into the non-repeated field.
217func (o UnmarshalOptions) unmarshalSingular(input text.Value, fd pref.FieldDescriptor, knownFields pref.KnownFields) error {
218 num := fd.Number()
219
220 var nerr errors.NonFatal
221 var val pref.Value
222 switch fd.Kind() {
223 case pref.MessageKind, pref.GroupKind:
224 if input.Type() != text.Message {
225 return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
226 }
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800227 m := knownFields.NewMessage(num)
Herbie Ong800c9902018-12-06 15:28:53 -0800228 if err := o.unmarshalMessage(input.Message(), m); !nerr.Merge(err) {
229 return err
230 }
231 val = pref.ValueOf(m)
232 default:
233 var err error
234 val, err = unmarshalScalar(input, fd)
235 if !nerr.Merge(err) {
236 return err
237 }
238 }
239 knownFields.Set(num, val)
240
241 return nerr.E
242}
243
244// unmarshalRepeated unmarshals given text.Value into a repeated field. Caller should only
245// call this for cardinality=repeated.
246func (o UnmarshalOptions) unmarshalRepeated(input text.Value, fd pref.FieldDescriptor, knownFields pref.KnownFields) error {
247 var items []text.Value
248 // If input is not a list, turn it into a list.
249 if input.Type() != text.List {
250 items = []text.Value{input}
251 } else {
252 items = input.List()
253 }
254
255 var nerr errors.NonFatal
256 num := fd.Number()
257 val := knownFields.Get(num)
258 if !fd.IsMap() {
259 if err := o.unmarshalList(items, fd, val.List()); !nerr.Merge(err) {
260 return err
261 }
262 } else {
263 if err := o.unmarshalMap(items, fd, val.Map()); !nerr.Merge(err) {
264 return err
265 }
266 }
267
268 return nerr.E
269}
270
271// unmarshalScalar converts the given text.Value to a scalar/enum protoreflect.Value specified in
272// the given FieldDescriptor. Caller should not pass in a FieldDescriptor for a message/group kind.
273func unmarshalScalar(input text.Value, fd pref.FieldDescriptor) (pref.Value, error) {
274 const b32 = false
275 const b64 = true
276
277 switch kind := fd.Kind(); kind {
278 case pref.BoolKind:
279 if b, ok := input.Bool(); ok {
280 return pref.ValueOf(bool(b)), nil
281 }
282 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
283 if n, ok := input.Int(b32); ok {
284 return pref.ValueOf(int32(n)), nil
285 }
286 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
287 if n, ok := input.Int(b64); ok {
288 return pref.ValueOf(int64(n)), nil
289 }
290 case pref.Uint32Kind, pref.Fixed32Kind:
291 if n, ok := input.Uint(b32); ok {
292 return pref.ValueOf(uint32(n)), nil
293 }
294 case pref.Uint64Kind, pref.Fixed64Kind:
295 if n, ok := input.Uint(b64); ok {
296 return pref.ValueOf(uint64(n)), nil
297 }
298 case pref.FloatKind:
Herbie Ong250c6ea2019-03-12 20:55:10 -0700299 if n, ok := input.Float(b32); ok {
Herbie Ong800c9902018-12-06 15:28:53 -0800300 return pref.ValueOf(float32(n)), nil
301 }
302 case pref.DoubleKind:
Herbie Ong250c6ea2019-03-12 20:55:10 -0700303 if n, ok := input.Float(b64); ok {
Herbie Ong800c9902018-12-06 15:28:53 -0800304 return pref.ValueOf(float64(n)), nil
305 }
306 case pref.StringKind:
307 if input.Type() == text.String {
308 return pref.ValueOf(string(input.String())), nil
309 }
310 case pref.BytesKind:
311 if input.Type() == text.String {
312 return pref.ValueOf([]byte(input.String())), nil
313 }
314 case pref.EnumKind:
315 // If input is int32, use directly.
316 if n, ok := input.Int(b32); ok {
317 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong66c365c2019-01-04 14:08:41 -0800318 }
319 if name, ok := input.Name(); ok {
320 // Lookup EnumNumber based on name.
321 if enumVal := fd.EnumType().Values().ByName(name); enumVal != nil {
322 return pref.ValueOf(enumVal.Number()), nil
Herbie Ong800c9902018-12-06 15:28:53 -0800323 }
324 }
325 default:
326 panic(fmt.Sprintf("invalid scalar kind %v", kind))
327 }
328
329 return pref.Value{}, errors.New("%v contains invalid scalar value: %v", fd.FullName(), input)
330}
331
332// unmarshalList unmarshals given []text.Value into given protoreflect.List.
333func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDescriptor, list pref.List) error {
334 var nerr errors.NonFatal
335
336 switch fd.Kind() {
337 case pref.MessageKind, pref.GroupKind:
338 for _, input := range inputList {
339 if input.Type() != text.Message {
340 return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
341 }
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800342 m := list.NewMessage()
Herbie Ong800c9902018-12-06 15:28:53 -0800343 if err := o.unmarshalMessage(input.Message(), m); !nerr.Merge(err) {
344 return err
345 }
346 list.Append(pref.ValueOf(m))
347 }
348 default:
349 for _, input := range inputList {
350 val, err := unmarshalScalar(input, fd)
351 if !nerr.Merge(err) {
352 return err
353 }
354 list.Append(val)
355 }
356 }
357
358 return nerr.E
359}
360
361// unmarshalMap unmarshals given []text.Value into given protoreflect.Map.
362func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescriptor, mmap pref.Map) error {
363 var nerr errors.NonFatal
364 fields := fd.MessageType().Fields()
365 keyDesc := fields.ByNumber(1)
366 valDesc := fields.ByNumber(2)
367
368 // Determine ahead whether map entry is a scalar type or a message type in order to call the
369 // appropriate unmarshalMapValue func inside the for loop below.
Herbie Ong66c365c2019-01-04 14:08:41 -0800370 unmarshalMapValue := unmarshalMapScalarValue
Herbie Ong800c9902018-12-06 15:28:53 -0800371 switch valDesc.Kind() {
372 case pref.MessageKind, pref.GroupKind:
373 unmarshalMapValue = o.unmarshalMapMessageValue
374 }
375
376 for _, entry := range input {
377 if entry.Type() != text.Message {
378 return errors.New("%v contains invalid map entry: %v", fd.FullName(), entry)
379 }
380 tkey, tval, err := parseMapEntry(entry.Message(), fd.FullName())
381 if !nerr.Merge(err) {
382 return err
383 }
384 pkey, err := unmarshalMapKey(tkey, keyDesc)
385 if !nerr.Merge(err) {
386 return err
387 }
388 err = unmarshalMapValue(tval, pkey, valDesc, mmap)
389 if !nerr.Merge(err) {
390 return err
391 }
392 }
393
394 return nerr.E
395}
396
397// parseMapEntry parses [][2]text.Value for field names key and value, and return corresponding
398// field values. If there are duplicate field names, the value for the last field is returned. If
399// the field name does not exist, it will return the zero value of text.Value. It will return an
400// error if there are unknown field names.
401func parseMapEntry(mapEntry [][2]text.Value, name pref.FullName) (key text.Value, value text.Value, err error) {
402 for _, field := range mapEntry {
403 keyStr, ok := field[0].Name()
404 if ok {
405 switch keyStr {
406 case "key":
407 if key.Type() != 0 {
408 return key, value, errors.New("%v contains duplicate key field", name)
409 }
410 key = field[1]
411 case "value":
412 if value.Type() != 0 {
413 return key, value, errors.New("%v contains duplicate value field", name)
414 }
415 value = field[1]
416 default:
417 ok = false
418 }
419 }
420 if !ok {
421 // TODO: Do not return error if ignore unknown option is added and enabled.
422 return key, value, errors.New("%v contains unknown map entry name: %v", name, field[0])
423 }
424 }
425 return key, value, nil
426}
427
428// unmarshalMapKey converts given text.Value into a protoreflect.MapKey. A map key type is any
429// integral or string type.
430func unmarshalMapKey(input text.Value, fd pref.FieldDescriptor) (pref.MapKey, error) {
431 // If input is not set, use the zero value.
432 if input.Type() == 0 {
433 return fd.Default().MapKey(), nil
434 }
435
436 val, err := unmarshalScalar(input, fd)
437 if err != nil {
438 return pref.MapKey{}, errors.New("%v contains invalid key: %v", fd.FullName(), input)
439 }
440 return val.MapKey(), nil
441}
442
443// unmarshalMapMessageValue unmarshals given message-type text.Value into a protoreflect.Map for
444// the given MapKey.
445func (o UnmarshalOptions) unmarshalMapMessageValue(input text.Value, pkey pref.MapKey, _ pref.FieldDescriptor, mmap pref.Map) error {
446 var nerr errors.NonFatal
447 var value [][2]text.Value
448 if input.Type() != 0 {
449 value = input.Message()
450 }
Joe Tsai3bc7d6f2019-01-09 02:57:13 -0800451 m := mmap.NewMessage()
Herbie Ong800c9902018-12-06 15:28:53 -0800452 if err := o.unmarshalMessage(value, m); !nerr.Merge(err) {
453 return err
454 }
455 mmap.Set(pkey, pref.ValueOf(m))
456 return nerr.E
457}
458
459// unmarshalMapScalarValue unmarshals given scalar-type text.Value into a protoreflect.Map
460// for the given MapKey.
Herbie Ong66c365c2019-01-04 14:08:41 -0800461func unmarshalMapScalarValue(input text.Value, pkey pref.MapKey, fd pref.FieldDescriptor, mmap pref.Map) error {
Herbie Ong800c9902018-12-06 15:28:53 -0800462 var val pref.Value
463 if input.Type() == 0 {
464 val = fd.Default()
465 } else {
466 var err error
467 val, err = unmarshalScalar(input, fd)
468 if err != nil {
469 return err
470 }
471 }
472 mmap.Set(pkey, val)
473 return nil
474}
Herbie Ong66c365c2019-01-04 14:08:41 -0800475
476// isExpandedAny returns true if given [][2]text.Value may be an expanded Any that contains only one
477// field with key type of text.String type and value type of text.Message.
478func isExpandedAny(tmsg [][2]text.Value) bool {
479 if len(tmsg) != 1 {
480 return false
481 }
482
483 field := tmsg[0]
484 return field[0].Type() == text.String && field[1].Type() == text.Message
485}
486
487// unmarshalAny unmarshals an expanded Any textproto. This method assumes that the given
488// tfield has key type of text.String and value type of text.Message.
489func (o UnmarshalOptions) unmarshalAny(tfield [2]text.Value, knownFields pref.KnownFields) error {
490 var nerr errors.NonFatal
491
492 typeURL := tfield[0].String()
493 value := tfield[1].Message()
494
495 mt, err := o.Resolver.FindMessageByURL(typeURL)
496 if !nerr.Merge(err) {
497 return errors.New("unable to resolve message [%v]: %v", typeURL, err)
498 }
499 // Create new message for the embedded message type and unmarshal the
500 // value into it.
501 m := mt.New()
502 if err := o.unmarshalMessage(value, m); !nerr.Merge(err) {
503 return err
504 }
505 // Serialize the embedded message and assign the resulting bytes to the value field.
Damien Neil96c229a2019-04-03 12:17:24 -0700506 b, err := proto.MarshalOptions{
507 AllowPartial: o.AllowPartial,
508 Deterministic: true,
509 }.Marshal(m.Interface())
Herbie Ong66c365c2019-01-04 14:08:41 -0800510 if !nerr.Merge(err) {
511 return err
512 }
513
Herbie Onge1e34932019-03-29 01:05:57 -0700514 knownFields.Set(fieldnum.Any_TypeUrl, pref.ValueOf(typeURL))
515 knownFields.Set(fieldnum.Any_Value, pref.ValueOf(b))
Herbie Ong66c365c2019-01-04 14:08:41 -0800516
517 return nerr.E
518}