blob: 27d7bf13bc7b87c3e9d592663128539c37796347 [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"
9
10 "github.com/golang/protobuf/v2/internal/encoding/text"
11 "github.com/golang/protobuf/v2/internal/errors"
12 "github.com/golang/protobuf/v2/internal/pragma"
13 "github.com/golang/protobuf/v2/internal/set"
14 "github.com/golang/protobuf/v2/proto"
15 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Ongc525c972018-12-18 18:04:31 -080016 "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ong800c9902018-12-06 15:28:53 -080017)
18
19// Unmarshal reads the given []byte into the given proto.Message.
20// TODO: may want to describe when Unmarshal returns error.
21func Unmarshal(m proto.Message, b []byte) error {
22 return UnmarshalOptions{}.Unmarshal(m, b)
23}
24
25// UnmarshalOptions is a configurable textproto format parser.
26type UnmarshalOptions struct {
27 pragma.NoUnkeyedLiterals
Herbie Ongc525c972018-12-18 18:04:31 -080028
29 // Resolver is the registry used for type lookups when unmarshaling extensions
30 // and processing Any. If Resolver is not set, unmarshaling will default to
31 // using protoregistry.GlobalTypes.
32 Resolver *protoregistry.Types
Herbie Ong800c9902018-12-06 15:28:53 -080033}
34
35// Unmarshal reads the given []byte and populates the given proto.Message using options in
36// UnmarshalOptions object.
37func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
38 var nerr errors.NonFatal
39
40 mr := m.ProtoReflect()
41 // Clear all fields before populating it.
42 // TODO: Determine if this needs to be consistent with jsonpb and binary unmarshal where
43 // behavior is to merge values into existing message. If decision is to not clear the fields
44 // ahead, code will need to be updated properly when merging nested messages.
45 resetMessage(mr)
46
47 // Parse into text.Value of message type.
48 val, err := text.Unmarshal(b)
49 if !nerr.Merge(err) {
50 return err
51 }
52
Herbie Ongc525c972018-12-18 18:04:31 -080053 if o.Resolver == nil {
54 o.Resolver = protoregistry.GlobalTypes
55 }
Herbie Ong800c9902018-12-06 15:28:53 -080056 err = o.unmarshalMessage(val.Message(), mr)
57 if !nerr.Merge(err) {
58 return err
59 }
60
61 return nerr.E
62}
63
64// resetMessage clears all fields of given protoreflect.Message.
65// TODO: This should go into the proto package.
66func resetMessage(m pref.Message) {
67 knownFields := m.KnownFields()
68 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
69 knownFields.Clear(num)
70 return true
71 })
72 unknownFields := m.UnknownFields()
73 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
74 unknownFields.Set(num, nil)
75 return true
76 })
Herbie Ong800c9902018-12-06 15:28:53 -080077 extTypes := knownFields.ExtensionTypes()
78 extTypes.Range(func(xt pref.ExtensionType) bool {
79 extTypes.Remove(xt)
80 return true
81 })
82}
83
84// unmarshalMessage unmarshals a [][2]text.Value message into the given protoreflect.Message.
85func (o UnmarshalOptions) unmarshalMessage(tmsg [][2]text.Value, m pref.Message) error {
86 var nerr errors.NonFatal
87
88 msgType := m.Type()
89 fieldDescs := msgType.Fields()
Herbie Ong7c624e22018-12-13 14:41:22 -080090 reservedNames := msgType.ReservedNames()
Herbie Ong800c9902018-12-06 15:28:53 -080091 knownFields := m.KnownFields()
Herbie Ongc525c972018-12-18 18:04:31 -080092 xtTypes := knownFields.ExtensionTypes()
Herbie Ong800c9902018-12-06 15:28:53 -080093 var reqNums set.Ints
94 var seenNums set.Ints
95
96 for _, tfield := range tmsg {
97 tkey := tfield[0]
98 tval := tfield[1]
99
100 var fd pref.FieldDescriptor
Herbie Ongc525c972018-12-18 18:04:31 -0800101 var name pref.Name
102 switch tkey.Type() {
103 case text.Name:
104 name, _ = tkey.Name()
Herbie Ong800c9902018-12-06 15:28:53 -0800105 fd = fieldDescs.ByName(name)
Herbie Ongc525c972018-12-18 18:04:31 -0800106 case text.String:
107 // TODO: Handle Any expansions here as well.
108
109 // Handle extensions. Extensions have to be registered first in the message's
110 // ExtensionTypes before setting a value to it.
111 xtName := pref.FullName(tkey.String())
112 // Check first if it is already registered. This is the case for repeated fields.
113 xt := xtTypes.ByName(xtName)
114 if xt == nil {
115 var err error
116 xt, err = o.Resolver.FindExtensionByName(xtName)
117 if err != nil && err != protoregistry.NotFound {
118 return err
119 }
120 if xt != nil {
121 xtTypes.Register(xt)
122 }
123 }
124 fd = xt
Herbie Ong800c9902018-12-06 15:28:53 -0800125 }
Herbie Ongc525c972018-12-18 18:04:31 -0800126
Herbie Ong800c9902018-12-06 15:28:53 -0800127 if fd == nil {
Herbie Ong7c624e22018-12-13 14:41:22 -0800128 // Ignore reserved names.
129 if reservedNames.Has(name) {
130 continue
131 }
Herbie Ong800c9902018-12-06 15:28:53 -0800132 // TODO: Can provide option to ignore unknown message fields.
Herbie Ong800c9902018-12-06 15:28:53 -0800133 return errors.New("%v contains unknown field: %v", msgType.FullName(), tkey)
134 }
135
136 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
137 // Map or list fields have cardinality of repeated.
138 if err := o.unmarshalRepeated(tval, fd, knownFields); !nerr.Merge(err) {
139 return err
140 }
141 } else {
142 // Required or optional fields.
143 num := uint64(fd.Number())
144 if seenNums.Has(num) {
145 return errors.New("non-repeated field %v is repeated", fd.FullName())
146 }
147 if err := o.unmarshalSingular(tval, fd, knownFields); !nerr.Merge(err) {
148 return err
149 }
150 if cardinality == pref.Required {
151 reqNums.Set(num)
152 }
153 seenNums.Set(num)
154 }
155 }
156
157 // Check for any missing required fields.
158 allReqNums := msgType.RequiredNumbers()
159 if reqNums.Len() != allReqNums.Len() {
160 for i := 0; i < allReqNums.Len(); i++ {
161 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
162 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
163 }
164 }
165 }
166
167 return nerr.E
168}
169
170// unmarshalSingular unmarshals given text.Value into the non-repeated field.
171func (o UnmarshalOptions) unmarshalSingular(input text.Value, fd pref.FieldDescriptor, knownFields pref.KnownFields) error {
172 num := fd.Number()
173
174 var nerr errors.NonFatal
175 var val pref.Value
176 switch fd.Kind() {
177 case pref.MessageKind, pref.GroupKind:
178 if input.Type() != text.Message {
179 return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
180 }
181 m := knownFields.NewMessage(num).ProtoReflect()
182 if err := o.unmarshalMessage(input.Message(), m); !nerr.Merge(err) {
183 return err
184 }
185 val = pref.ValueOf(m)
186 default:
187 var err error
188 val, err = unmarshalScalar(input, fd)
189 if !nerr.Merge(err) {
190 return err
191 }
192 }
193 knownFields.Set(num, val)
194
195 return nerr.E
196}
197
198// unmarshalRepeated unmarshals given text.Value into a repeated field. Caller should only
199// call this for cardinality=repeated.
200func (o UnmarshalOptions) unmarshalRepeated(input text.Value, fd pref.FieldDescriptor, knownFields pref.KnownFields) error {
201 var items []text.Value
202 // If input is not a list, turn it into a list.
203 if input.Type() != text.List {
204 items = []text.Value{input}
205 } else {
206 items = input.List()
207 }
208
209 var nerr errors.NonFatal
210 num := fd.Number()
211 val := knownFields.Get(num)
212 if !fd.IsMap() {
213 if err := o.unmarshalList(items, fd, val.List()); !nerr.Merge(err) {
214 return err
215 }
216 } else {
217 if err := o.unmarshalMap(items, fd, val.Map()); !nerr.Merge(err) {
218 return err
219 }
220 }
221
222 return nerr.E
223}
224
225// unmarshalScalar converts the given text.Value to a scalar/enum protoreflect.Value specified in
226// the given FieldDescriptor. Caller should not pass in a FieldDescriptor for a message/group kind.
227func unmarshalScalar(input text.Value, fd pref.FieldDescriptor) (pref.Value, error) {
228 const b32 = false
229 const b64 = true
230
231 switch kind := fd.Kind(); kind {
232 case pref.BoolKind:
233 if b, ok := input.Bool(); ok {
234 return pref.ValueOf(bool(b)), nil
235 }
236 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
237 if n, ok := input.Int(b32); ok {
238 return pref.ValueOf(int32(n)), nil
239 }
240 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
241 if n, ok := input.Int(b64); ok {
242 return pref.ValueOf(int64(n)), nil
243 }
244 case pref.Uint32Kind, pref.Fixed32Kind:
245 if n, ok := input.Uint(b32); ok {
246 return pref.ValueOf(uint32(n)), nil
247 }
248 case pref.Uint64Kind, pref.Fixed64Kind:
249 if n, ok := input.Uint(b64); ok {
250 return pref.ValueOf(uint64(n)), nil
251 }
252 case pref.FloatKind:
253 if n, ok := input.Float(b32); ok {
254 return pref.ValueOf(float32(n)), nil
255 }
256 case pref.DoubleKind:
257 if n, ok := input.Float(b64); ok {
258 return pref.ValueOf(float64(n)), nil
259 }
260 case pref.StringKind:
261 if input.Type() == text.String {
262 return pref.ValueOf(string(input.String())), nil
263 }
264 case pref.BytesKind:
265 if input.Type() == text.String {
266 return pref.ValueOf([]byte(input.String())), nil
267 }
268 case pref.EnumKind:
269 // If input is int32, use directly.
270 if n, ok := input.Int(b32); ok {
271 return pref.ValueOf(pref.EnumNumber(n)), nil
272 } else {
273 if name, ok := input.Name(); ok {
274 // Lookup EnumNumber based on name.
275 if enumVal := fd.EnumType().Values().ByName(name); enumVal != nil {
276 return pref.ValueOf(enumVal.Number()), nil
277 }
278 }
279 }
280 default:
281 panic(fmt.Sprintf("invalid scalar kind %v", kind))
282 }
283
284 return pref.Value{}, errors.New("%v contains invalid scalar value: %v", fd.FullName(), input)
285}
286
287// unmarshalList unmarshals given []text.Value into given protoreflect.List.
288func (o UnmarshalOptions) unmarshalList(inputList []text.Value, fd pref.FieldDescriptor, list pref.List) error {
289 var nerr errors.NonFatal
290
291 switch fd.Kind() {
292 case pref.MessageKind, pref.GroupKind:
293 for _, input := range inputList {
294 if input.Type() != text.Message {
295 return errors.New("%v contains invalid message/group value: %v", fd.FullName(), input)
296 }
297 m := list.NewMessage().ProtoReflect()
298 if err := o.unmarshalMessage(input.Message(), m); !nerr.Merge(err) {
299 return err
300 }
301 list.Append(pref.ValueOf(m))
302 }
303 default:
304 for _, input := range inputList {
305 val, err := unmarshalScalar(input, fd)
306 if !nerr.Merge(err) {
307 return err
308 }
309 list.Append(val)
310 }
311 }
312
313 return nerr.E
314}
315
316// unmarshalMap unmarshals given []text.Value into given protoreflect.Map.
317func (o UnmarshalOptions) unmarshalMap(input []text.Value, fd pref.FieldDescriptor, mmap pref.Map) error {
318 var nerr errors.NonFatal
319 fields := fd.MessageType().Fields()
320 keyDesc := fields.ByNumber(1)
321 valDesc := fields.ByNumber(2)
322
323 // Determine ahead whether map entry is a scalar type or a message type in order to call the
324 // appropriate unmarshalMapValue func inside the for loop below.
325 unmarshalMapValue := o.unmarshalMapScalarValue
326 switch valDesc.Kind() {
327 case pref.MessageKind, pref.GroupKind:
328 unmarshalMapValue = o.unmarshalMapMessageValue
329 }
330
331 for _, entry := range input {
332 if entry.Type() != text.Message {
333 return errors.New("%v contains invalid map entry: %v", fd.FullName(), entry)
334 }
335 tkey, tval, err := parseMapEntry(entry.Message(), fd.FullName())
336 if !nerr.Merge(err) {
337 return err
338 }
339 pkey, err := unmarshalMapKey(tkey, keyDesc)
340 if !nerr.Merge(err) {
341 return err
342 }
343 err = unmarshalMapValue(tval, pkey, valDesc, mmap)
344 if !nerr.Merge(err) {
345 return err
346 }
347 }
348
349 return nerr.E
350}
351
352// parseMapEntry parses [][2]text.Value for field names key and value, and return corresponding
353// field values. If there are duplicate field names, the value for the last field is returned. If
354// the field name does not exist, it will return the zero value of text.Value. It will return an
355// error if there are unknown field names.
356func parseMapEntry(mapEntry [][2]text.Value, name pref.FullName) (key text.Value, value text.Value, err error) {
357 for _, field := range mapEntry {
358 keyStr, ok := field[0].Name()
359 if ok {
360 switch keyStr {
361 case "key":
362 if key.Type() != 0 {
363 return key, value, errors.New("%v contains duplicate key field", name)
364 }
365 key = field[1]
366 case "value":
367 if value.Type() != 0 {
368 return key, value, errors.New("%v contains duplicate value field", name)
369 }
370 value = field[1]
371 default:
372 ok = false
373 }
374 }
375 if !ok {
376 // TODO: Do not return error if ignore unknown option is added and enabled.
377 return key, value, errors.New("%v contains unknown map entry name: %v", name, field[0])
378 }
379 }
380 return key, value, nil
381}
382
383// unmarshalMapKey converts given text.Value into a protoreflect.MapKey. A map key type is any
384// integral or string type.
385func unmarshalMapKey(input text.Value, fd pref.FieldDescriptor) (pref.MapKey, error) {
386 // If input is not set, use the zero value.
387 if input.Type() == 0 {
388 return fd.Default().MapKey(), nil
389 }
390
391 val, err := unmarshalScalar(input, fd)
392 if err != nil {
393 return pref.MapKey{}, errors.New("%v contains invalid key: %v", fd.FullName(), input)
394 }
395 return val.MapKey(), nil
396}
397
398// unmarshalMapMessageValue unmarshals given message-type text.Value into a protoreflect.Map for
399// the given MapKey.
400func (o UnmarshalOptions) unmarshalMapMessageValue(input text.Value, pkey pref.MapKey, _ pref.FieldDescriptor, mmap pref.Map) error {
401 var nerr errors.NonFatal
402 var value [][2]text.Value
403 if input.Type() != 0 {
404 value = input.Message()
405 }
406 m := mmap.NewMessage().ProtoReflect()
407 if err := o.unmarshalMessage(value, m); !nerr.Merge(err) {
408 return err
409 }
410 mmap.Set(pkey, pref.ValueOf(m))
411 return nerr.E
412}
413
414// unmarshalMapScalarValue unmarshals given scalar-type text.Value into a protoreflect.Map
415// for the given MapKey.
416func (o UnmarshalOptions) unmarshalMapScalarValue(input text.Value, pkey pref.MapKey, fd pref.FieldDescriptor, mmap pref.Map) error {
417 var val pref.Value
418 if input.Type() == 0 {
419 val = fd.Default()
420 } else {
421 var err error
422 val, err = unmarshalScalar(input, fd)
423 if err != nil {
424 return err
425 }
426 }
427 mmap.Set(pkey, val)
428 return nil
429}