podman

Форк
0
685 строк · 17.9 Кб
1
// Copyright 2019 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

5
package protojson
6

7
import (
8
	"encoding/base64"
9
	"fmt"
10
	"math"
11
	"strconv"
12
	"strings"
13

14
	"google.golang.org/protobuf/encoding/protowire"
15
	"google.golang.org/protobuf/internal/encoding/json"
16
	"google.golang.org/protobuf/internal/encoding/messageset"
17
	"google.golang.org/protobuf/internal/errors"
18
	"google.golang.org/protobuf/internal/flags"
19
	"google.golang.org/protobuf/internal/genid"
20
	"google.golang.org/protobuf/internal/pragma"
21
	"google.golang.org/protobuf/internal/set"
22
	"google.golang.org/protobuf/proto"
23
	"google.golang.org/protobuf/reflect/protoreflect"
24
	"google.golang.org/protobuf/reflect/protoregistry"
25
)
26

27
// Unmarshal reads the given []byte into the given [proto.Message].
28
// The provided message must be mutable (e.g., a non-nil pointer to a message).
29
func Unmarshal(b []byte, m proto.Message) error {
30
	return UnmarshalOptions{}.Unmarshal(b, m)
31
}
32

33
// UnmarshalOptions is a configurable JSON format parser.
34
type UnmarshalOptions struct {
35
	pragma.NoUnkeyedLiterals
36

37
	// If AllowPartial is set, input for messages that will result in missing
38
	// required fields will not return an error.
39
	AllowPartial bool
40

41
	// If DiscardUnknown is set, unknown fields and enum name values are ignored.
42
	DiscardUnknown bool
43

44
	// Resolver is used for looking up types when unmarshaling
45
	// google.protobuf.Any messages or extension fields.
46
	// If nil, this defaults to using protoregistry.GlobalTypes.
47
	Resolver interface {
48
		protoregistry.MessageTypeResolver
49
		protoregistry.ExtensionTypeResolver
50
	}
51

52
	// RecursionLimit limits how deeply messages may be nested.
53
	// If zero, a default limit is applied.
54
	RecursionLimit int
55
}
56

57
// Unmarshal reads the given []byte and populates the given [proto.Message]
58
// using options in the UnmarshalOptions object.
59
// It will clear the message first before setting the fields.
60
// If it returns an error, the given message may be partially set.
61
// The provided message must be mutable (e.g., a non-nil pointer to a message).
62
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
63
	return o.unmarshal(b, m)
64
}
65

66
// unmarshal is a centralized function that all unmarshal operations go through.
67
// For profiling purposes, avoid changing the name of this function or
68
// introducing other code paths for unmarshal that do not go through this.
69
func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
70
	proto.Reset(m)
71

72
	if o.Resolver == nil {
73
		o.Resolver = protoregistry.GlobalTypes
74
	}
75
	if o.RecursionLimit == 0 {
76
		o.RecursionLimit = protowire.DefaultRecursionLimit
77
	}
78

79
	dec := decoder{json.NewDecoder(b), o}
80
	if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
81
		return err
82
	}
83

84
	// Check for EOF.
85
	tok, err := dec.Read()
86
	if err != nil {
87
		return err
88
	}
89
	if tok.Kind() != json.EOF {
90
		return dec.unexpectedTokenError(tok)
91
	}
92

93
	if o.AllowPartial {
94
		return nil
95
	}
96
	return proto.CheckInitialized(m)
97
}
98

99
type decoder struct {
100
	*json.Decoder
101
	opts UnmarshalOptions
102
}
103

104
// newError returns an error object with position info.
105
func (d decoder) newError(pos int, f string, x ...interface{}) error {
106
	line, column := d.Position(pos)
107
	head := fmt.Sprintf("(line %d:%d): ", line, column)
108
	return errors.New(head+f, x...)
109
}
110

111
// unexpectedTokenError returns a syntax error for the given unexpected token.
112
func (d decoder) unexpectedTokenError(tok json.Token) error {
113
	return d.syntaxError(tok.Pos(), "unexpected token %s", tok.RawString())
114
}
115

116
// syntaxError returns a syntax error for given position.
117
func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
118
	line, column := d.Position(pos)
119
	head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
120
	return errors.New(head+f, x...)
121
}
122

123
// unmarshalMessage unmarshals a message into the given protoreflect.Message.
124
func (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error {
125
	d.opts.RecursionLimit--
126
	if d.opts.RecursionLimit < 0 {
127
		return errors.New("exceeded max recursion depth")
128
	}
129
	if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil {
130
		return unmarshal(d, m)
131
	}
132

133
	tok, err := d.Read()
134
	if err != nil {
135
		return err
136
	}
137
	if tok.Kind() != json.ObjectOpen {
138
		return d.unexpectedTokenError(tok)
139
	}
140

141
	messageDesc := m.Descriptor()
142
	if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
143
		return errors.New("no support for proto1 MessageSets")
144
	}
145

146
	var seenNums set.Ints
147
	var seenOneofs set.Ints
148
	fieldDescs := messageDesc.Fields()
149
	for {
150
		// Read field name.
151
		tok, err := d.Read()
152
		if err != nil {
153
			return err
154
		}
155
		switch tok.Kind() {
156
		default:
157
			return d.unexpectedTokenError(tok)
158
		case json.ObjectClose:
159
			return nil
160
		case json.Name:
161
			// Continue below.
162
		}
163

164
		name := tok.Name()
165
		// Unmarshaling a non-custom embedded message in Any will contain the
166
		// JSON field "@type" which should be skipped because it is not a field
167
		// of the embedded message, but simply an artifact of the Any format.
168
		if skipTypeURL && name == "@type" {
169
			d.Read()
170
			continue
171
		}
172

173
		// Get the FieldDescriptor.
174
		var fd protoreflect.FieldDescriptor
175
		if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
176
			// Only extension names are in [name] format.
177
			extName := protoreflect.FullName(name[1 : len(name)-1])
178
			extType, err := d.opts.Resolver.FindExtensionByName(extName)
179
			if err != nil && err != protoregistry.NotFound {
180
				return d.newError(tok.Pos(), "unable to resolve %s: %v", tok.RawString(), err)
181
			}
182
			if extType != nil {
183
				fd = extType.TypeDescriptor()
184
				if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
185
					return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
186
				}
187
			}
188
		} else {
189
			// The name can either be the JSON name or the proto field name.
190
			fd = fieldDescs.ByJSONName(name)
191
			if fd == nil {
192
				fd = fieldDescs.ByTextName(name)
193
			}
194
		}
195
		if flags.ProtoLegacy {
196
			if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
197
				fd = nil // reset since the weak reference is not linked in
198
			}
199
		}
200

201
		if fd == nil {
202
			// Field is unknown.
203
			if d.opts.DiscardUnknown {
204
				if err := d.skipJSONValue(); err != nil {
205
					return err
206
				}
207
				continue
208
			}
209
			return d.newError(tok.Pos(), "unknown field %v", tok.RawString())
210
		}
211

212
		// Do not allow duplicate fields.
213
		num := uint64(fd.Number())
214
		if seenNums.Has(num) {
215
			return d.newError(tok.Pos(), "duplicate field %v", tok.RawString())
216
		}
217
		seenNums.Set(num)
218

219
		// No need to set values for JSON null unless the field type is
220
		// google.protobuf.Value or google.protobuf.NullValue.
221
		if tok, _ := d.Peek(); tok.Kind() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
222
			d.Read()
223
			continue
224
		}
225

226
		switch {
227
		case fd.IsList():
228
			list := m.Mutable(fd).List()
229
			if err := d.unmarshalList(list, fd); err != nil {
230
				return err
231
			}
232
		case fd.IsMap():
233
			mmap := m.Mutable(fd).Map()
234
			if err := d.unmarshalMap(mmap, fd); err != nil {
235
				return err
236
			}
237
		default:
238
			// If field is a oneof, check if it has already been set.
239
			if od := fd.ContainingOneof(); od != nil {
240
				idx := uint64(od.Index())
241
				if seenOneofs.Has(idx) {
242
					return d.newError(tok.Pos(), "error parsing %s, oneof %v is already set", tok.RawString(), od.FullName())
243
				}
244
				seenOneofs.Set(idx)
245
			}
246

247
			// Required or optional fields.
248
			if err := d.unmarshalSingular(m, fd); err != nil {
249
				return err
250
			}
251
		}
252
	}
253
}
254

255
func isKnownValue(fd protoreflect.FieldDescriptor) bool {
256
	md := fd.Message()
257
	return md != nil && md.FullName() == genid.Value_message_fullname
258
}
259

260
func isNullValue(fd protoreflect.FieldDescriptor) bool {
261
	ed := fd.Enum()
262
	return ed != nil && ed.FullName() == genid.NullValue_enum_fullname
263
}
264

265
// unmarshalSingular unmarshals to the non-repeated field specified
266
// by the given FieldDescriptor.
267
func (d decoder) unmarshalSingular(m protoreflect.Message, fd protoreflect.FieldDescriptor) error {
268
	var val protoreflect.Value
269
	var err error
270
	switch fd.Kind() {
271
	case protoreflect.MessageKind, protoreflect.GroupKind:
272
		val = m.NewField(fd)
273
		err = d.unmarshalMessage(val.Message(), false)
274
	default:
275
		val, err = d.unmarshalScalar(fd)
276
	}
277

278
	if err != nil {
279
		return err
280
	}
281
	if val.IsValid() {
282
		m.Set(fd, val)
283
	}
284
	return nil
285
}
286

287
// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
288
// the given FieldDescriptor.
289
func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
290
	const b32 int = 32
291
	const b64 int = 64
292

293
	tok, err := d.Read()
294
	if err != nil {
295
		return protoreflect.Value{}, err
296
	}
297

298
	kind := fd.Kind()
299
	switch kind {
300
	case protoreflect.BoolKind:
301
		if tok.Kind() == json.Bool {
302
			return protoreflect.ValueOfBool(tok.Bool()), nil
303
		}
304

305
	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
306
		if v, ok := unmarshalInt(tok, b32); ok {
307
			return v, nil
308
		}
309

310
	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
311
		if v, ok := unmarshalInt(tok, b64); ok {
312
			return v, nil
313
		}
314

315
	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
316
		if v, ok := unmarshalUint(tok, b32); ok {
317
			return v, nil
318
		}
319

320
	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
321
		if v, ok := unmarshalUint(tok, b64); ok {
322
			return v, nil
323
		}
324

325
	case protoreflect.FloatKind:
326
		if v, ok := unmarshalFloat(tok, b32); ok {
327
			return v, nil
328
		}
329

330
	case protoreflect.DoubleKind:
331
		if v, ok := unmarshalFloat(tok, b64); ok {
332
			return v, nil
333
		}
334

335
	case protoreflect.StringKind:
336
		if tok.Kind() == json.String {
337
			return protoreflect.ValueOfString(tok.ParsedString()), nil
338
		}
339

340
	case protoreflect.BytesKind:
341
		if v, ok := unmarshalBytes(tok); ok {
342
			return v, nil
343
		}
344

345
	case protoreflect.EnumKind:
346
		if v, ok := unmarshalEnum(tok, fd, d.opts.DiscardUnknown); ok {
347
			return v, nil
348
		}
349

350
	default:
351
		panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind))
352
	}
353

354
	return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString())
355
}
356

357
func unmarshalInt(tok json.Token, bitSize int) (protoreflect.Value, bool) {
358
	switch tok.Kind() {
359
	case json.Number:
360
		return getInt(tok, bitSize)
361

362
	case json.String:
363
		// Decode number from string.
364
		s := strings.TrimSpace(tok.ParsedString())
365
		if len(s) != len(tok.ParsedString()) {
366
			return protoreflect.Value{}, false
367
		}
368
		dec := json.NewDecoder([]byte(s))
369
		tok, err := dec.Read()
370
		if err != nil {
371
			return protoreflect.Value{}, false
372
		}
373
		return getInt(tok, bitSize)
374
	}
375
	return protoreflect.Value{}, false
376
}
377

378
func getInt(tok json.Token, bitSize int) (protoreflect.Value, bool) {
379
	n, ok := tok.Int(bitSize)
380
	if !ok {
381
		return protoreflect.Value{}, false
382
	}
383
	if bitSize == 32 {
384
		return protoreflect.ValueOfInt32(int32(n)), true
385
	}
386
	return protoreflect.ValueOfInt64(n), true
387
}
388

389
func unmarshalUint(tok json.Token, bitSize int) (protoreflect.Value, bool) {
390
	switch tok.Kind() {
391
	case json.Number:
392
		return getUint(tok, bitSize)
393

394
	case json.String:
395
		// Decode number from string.
396
		s := strings.TrimSpace(tok.ParsedString())
397
		if len(s) != len(tok.ParsedString()) {
398
			return protoreflect.Value{}, false
399
		}
400
		dec := json.NewDecoder([]byte(s))
401
		tok, err := dec.Read()
402
		if err != nil {
403
			return protoreflect.Value{}, false
404
		}
405
		return getUint(tok, bitSize)
406
	}
407
	return protoreflect.Value{}, false
408
}
409

410
func getUint(tok json.Token, bitSize int) (protoreflect.Value, bool) {
411
	n, ok := tok.Uint(bitSize)
412
	if !ok {
413
		return protoreflect.Value{}, false
414
	}
415
	if bitSize == 32 {
416
		return protoreflect.ValueOfUint32(uint32(n)), true
417
	}
418
	return protoreflect.ValueOfUint64(n), true
419
}
420

421
func unmarshalFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) {
422
	switch tok.Kind() {
423
	case json.Number:
424
		return getFloat(tok, bitSize)
425

426
	case json.String:
427
		s := tok.ParsedString()
428
		switch s {
429
		case "NaN":
430
			if bitSize == 32 {
431
				return protoreflect.ValueOfFloat32(float32(math.NaN())), true
432
			}
433
			return protoreflect.ValueOfFloat64(math.NaN()), true
434
		case "Infinity":
435
			if bitSize == 32 {
436
				return protoreflect.ValueOfFloat32(float32(math.Inf(+1))), true
437
			}
438
			return protoreflect.ValueOfFloat64(math.Inf(+1)), true
439
		case "-Infinity":
440
			if bitSize == 32 {
441
				return protoreflect.ValueOfFloat32(float32(math.Inf(-1))), true
442
			}
443
			return protoreflect.ValueOfFloat64(math.Inf(-1)), true
444
		}
445

446
		// Decode number from string.
447
		if len(s) != len(strings.TrimSpace(s)) {
448
			return protoreflect.Value{}, false
449
		}
450
		dec := json.NewDecoder([]byte(s))
451
		tok, err := dec.Read()
452
		if err != nil {
453
			return protoreflect.Value{}, false
454
		}
455
		return getFloat(tok, bitSize)
456
	}
457
	return protoreflect.Value{}, false
458
}
459

460
func getFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) {
461
	n, ok := tok.Float(bitSize)
462
	if !ok {
463
		return protoreflect.Value{}, false
464
	}
465
	if bitSize == 32 {
466
		return protoreflect.ValueOfFloat32(float32(n)), true
467
	}
468
	return protoreflect.ValueOfFloat64(n), true
469
}
470

471
func unmarshalBytes(tok json.Token) (protoreflect.Value, bool) {
472
	if tok.Kind() != json.String {
473
		return protoreflect.Value{}, false
474
	}
475

476
	s := tok.ParsedString()
477
	enc := base64.StdEncoding
478
	if strings.ContainsAny(s, "-_") {
479
		enc = base64.URLEncoding
480
	}
481
	if len(s)%4 != 0 {
482
		enc = enc.WithPadding(base64.NoPadding)
483
	}
484
	b, err := enc.DecodeString(s)
485
	if err != nil {
486
		return protoreflect.Value{}, false
487
	}
488
	return protoreflect.ValueOfBytes(b), true
489
}
490

491
func unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor, discardUnknown bool) (protoreflect.Value, bool) {
492
	switch tok.Kind() {
493
	case json.String:
494
		// Lookup EnumNumber based on name.
495
		s := tok.ParsedString()
496
		if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil {
497
			return protoreflect.ValueOfEnum(enumVal.Number()), true
498
		}
499
		if discardUnknown {
500
			return protoreflect.Value{}, true
501
		}
502

503
	case json.Number:
504
		if n, ok := tok.Int(32); ok {
505
			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(n)), true
506
		}
507

508
	case json.Null:
509
		// This is only valid for google.protobuf.NullValue.
510
		if isNullValue(fd) {
511
			return protoreflect.ValueOfEnum(0), true
512
		}
513
	}
514

515
	return protoreflect.Value{}, false
516
}
517

518
func (d decoder) unmarshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error {
519
	tok, err := d.Read()
520
	if err != nil {
521
		return err
522
	}
523
	if tok.Kind() != json.ArrayOpen {
524
		return d.unexpectedTokenError(tok)
525
	}
526

527
	switch fd.Kind() {
528
	case protoreflect.MessageKind, protoreflect.GroupKind:
529
		for {
530
			tok, err := d.Peek()
531
			if err != nil {
532
				return err
533
			}
534

535
			if tok.Kind() == json.ArrayClose {
536
				d.Read()
537
				return nil
538
			}
539

540
			val := list.NewElement()
541
			if err := d.unmarshalMessage(val.Message(), false); err != nil {
542
				return err
543
			}
544
			list.Append(val)
545
		}
546
	default:
547
		for {
548
			tok, err := d.Peek()
549
			if err != nil {
550
				return err
551
			}
552

553
			if tok.Kind() == json.ArrayClose {
554
				d.Read()
555
				return nil
556
			}
557

558
			val, err := d.unmarshalScalar(fd)
559
			if err != nil {
560
				return err
561
			}
562
			if val.IsValid() {
563
				list.Append(val)
564
			}
565
		}
566
	}
567

568
	return nil
569
}
570

571
func (d decoder) unmarshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error {
572
	tok, err := d.Read()
573
	if err != nil {
574
		return err
575
	}
576
	if tok.Kind() != json.ObjectOpen {
577
		return d.unexpectedTokenError(tok)
578
	}
579

580
	// Determine ahead whether map entry is a scalar type or a message type in
581
	// order to call the appropriate unmarshalMapValue func inside the for loop
582
	// below.
583
	var unmarshalMapValue func() (protoreflect.Value, error)
584
	switch fd.MapValue().Kind() {
585
	case protoreflect.MessageKind, protoreflect.GroupKind:
586
		unmarshalMapValue = func() (protoreflect.Value, error) {
587
			val := mmap.NewValue()
588
			if err := d.unmarshalMessage(val.Message(), false); err != nil {
589
				return protoreflect.Value{}, err
590
			}
591
			return val, nil
592
		}
593
	default:
594
		unmarshalMapValue = func() (protoreflect.Value, error) {
595
			return d.unmarshalScalar(fd.MapValue())
596
		}
597
	}
598

599
Loop:
600
	for {
601
		// Read field name.
602
		tok, err := d.Read()
603
		if err != nil {
604
			return err
605
		}
606
		switch tok.Kind() {
607
		default:
608
			return d.unexpectedTokenError(tok)
609
		case json.ObjectClose:
610
			break Loop
611
		case json.Name:
612
			// Continue.
613
		}
614

615
		// Unmarshal field name.
616
		pkey, err := d.unmarshalMapKey(tok, fd.MapKey())
617
		if err != nil {
618
			return err
619
		}
620

621
		// Check for duplicate field name.
622
		if mmap.Has(pkey) {
623
			return d.newError(tok.Pos(), "duplicate map key %v", tok.RawString())
624
		}
625

626
		// Read and unmarshal field value.
627
		pval, err := unmarshalMapValue()
628
		if err != nil {
629
			return err
630
		}
631
		if pval.IsValid() {
632
			mmap.Set(pkey, pval)
633
		}
634
	}
635

636
	return nil
637
}
638

639
// unmarshalMapKey converts given token of Name kind into a protoreflect.MapKey.
640
// A map key type is any integral or string type.
641
func (d decoder) unmarshalMapKey(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.MapKey, error) {
642
	const b32 = 32
643
	const b64 = 64
644
	const base10 = 10
645

646
	name := tok.Name()
647
	kind := fd.Kind()
648
	switch kind {
649
	case protoreflect.StringKind:
650
		return protoreflect.ValueOfString(name).MapKey(), nil
651

652
	case protoreflect.BoolKind:
653
		switch name {
654
		case "true":
655
			return protoreflect.ValueOfBool(true).MapKey(), nil
656
		case "false":
657
			return protoreflect.ValueOfBool(false).MapKey(), nil
658
		}
659

660
	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
661
		if n, err := strconv.ParseInt(name, base10, b32); err == nil {
662
			return protoreflect.ValueOfInt32(int32(n)).MapKey(), nil
663
		}
664

665
	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
666
		if n, err := strconv.ParseInt(name, base10, b64); err == nil {
667
			return protoreflect.ValueOfInt64(int64(n)).MapKey(), nil
668
		}
669

670
	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
671
		if n, err := strconv.ParseUint(name, base10, b32); err == nil {
672
			return protoreflect.ValueOfUint32(uint32(n)).MapKey(), nil
673
		}
674

675
	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
676
		if n, err := strconv.ParseUint(name, base10, b64); err == nil {
677
			return protoreflect.ValueOfUint64(uint64(n)).MapKey(), nil
678
		}
679

680
	default:
681
		panic(fmt.Sprintf("invalid kind for map key: %v", kind))
682
	}
683

684
	return protoreflect.MapKey{}, d.newError(tok.Pos(), "invalid value for %v key: %s", kind, tok.RawString())
685
}
686

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.