podman

Форк
0
930 строк · 22.9 Кб
1
// Protocol Buffers for Go with Gadgets
2
//
3
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
4
// http://github.com/gogo/protobuf
5
//
6
// Go support for Protocol Buffers - Google's data interchange format
7
//
8
// Copyright 2010 The Go Authors.  All rights reserved.
9
// https://github.com/golang/protobuf
10
//
11
// Redistribution and use in source and binary forms, with or without
12
// modification, are permitted provided that the following conditions are
13
// met:
14
//
15
//     * Redistributions of source code must retain the above copyright
16
// notice, this list of conditions and the following disclaimer.
17
//     * Redistributions in binary form must reproduce the above
18
// copyright notice, this list of conditions and the following disclaimer
19
// in the documentation and/or other materials provided with the
20
// distribution.
21
//     * Neither the name of Google Inc. nor the names of its
22
// contributors may be used to endorse or promote products derived from
23
// this software without specific prior written permission.
24
//
25
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36

37
package proto
38

39
// Functions for writing the text protocol buffer format.
40

41
import (
42
	"bufio"
43
	"bytes"
44
	"encoding"
45
	"errors"
46
	"fmt"
47
	"io"
48
	"log"
49
	"math"
50
	"reflect"
51
	"sort"
52
	"strings"
53
	"sync"
54
	"time"
55
)
56

57
var (
58
	newline         = []byte("\n")
59
	spaces          = []byte("                                        ")
60
	endBraceNewline = []byte("}\n")
61
	backslashN      = []byte{'\\', 'n'}
62
	backslashR      = []byte{'\\', 'r'}
63
	backslashT      = []byte{'\\', 't'}
64
	backslashDQ     = []byte{'\\', '"'}
65
	backslashBS     = []byte{'\\', '\\'}
66
	posInf          = []byte("inf")
67
	negInf          = []byte("-inf")
68
	nan             = []byte("nan")
69
)
70

71
type writer interface {
72
	io.Writer
73
	WriteByte(byte) error
74
}
75

76
// textWriter is an io.Writer that tracks its indentation level.
77
type textWriter struct {
78
	ind      int
79
	complete bool // if the current position is a complete line
80
	compact  bool // whether to write out as a one-liner
81
	w        writer
82
}
83

84
func (w *textWriter) WriteString(s string) (n int, err error) {
85
	if !strings.Contains(s, "\n") {
86
		if !w.compact && w.complete {
87
			w.writeIndent()
88
		}
89
		w.complete = false
90
		return io.WriteString(w.w, s)
91
	}
92
	// WriteString is typically called without newlines, so this
93
	// codepath and its copy are rare.  We copy to avoid
94
	// duplicating all of Write's logic here.
95
	return w.Write([]byte(s))
96
}
97

98
func (w *textWriter) Write(p []byte) (n int, err error) {
99
	newlines := bytes.Count(p, newline)
100
	if newlines == 0 {
101
		if !w.compact && w.complete {
102
			w.writeIndent()
103
		}
104
		n, err = w.w.Write(p)
105
		w.complete = false
106
		return n, err
107
	}
108

109
	frags := bytes.SplitN(p, newline, newlines+1)
110
	if w.compact {
111
		for i, frag := range frags {
112
			if i > 0 {
113
				if err := w.w.WriteByte(' '); err != nil {
114
					return n, err
115
				}
116
				n++
117
			}
118
			nn, err := w.w.Write(frag)
119
			n += nn
120
			if err != nil {
121
				return n, err
122
			}
123
		}
124
		return n, nil
125
	}
126

127
	for i, frag := range frags {
128
		if w.complete {
129
			w.writeIndent()
130
		}
131
		nn, err := w.w.Write(frag)
132
		n += nn
133
		if err != nil {
134
			return n, err
135
		}
136
		if i+1 < len(frags) {
137
			if err := w.w.WriteByte('\n'); err != nil {
138
				return n, err
139
			}
140
			n++
141
		}
142
	}
143
	w.complete = len(frags[len(frags)-1]) == 0
144
	return n, nil
145
}
146

147
func (w *textWriter) WriteByte(c byte) error {
148
	if w.compact && c == '\n' {
149
		c = ' '
150
	}
151
	if !w.compact && w.complete {
152
		w.writeIndent()
153
	}
154
	err := w.w.WriteByte(c)
155
	w.complete = c == '\n'
156
	return err
157
}
158

159
func (w *textWriter) indent() { w.ind++ }
160

161
func (w *textWriter) unindent() {
162
	if w.ind == 0 {
163
		log.Print("proto: textWriter unindented too far")
164
		return
165
	}
166
	w.ind--
167
}
168

169
func writeName(w *textWriter, props *Properties) error {
170
	if _, err := w.WriteString(props.OrigName); err != nil {
171
		return err
172
	}
173
	if props.Wire != "group" {
174
		return w.WriteByte(':')
175
	}
176
	return nil
177
}
178

179
func requiresQuotes(u string) bool {
180
	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
181
	for _, ch := range u {
182
		switch {
183
		case ch == '.' || ch == '/' || ch == '_':
184
			continue
185
		case '0' <= ch && ch <= '9':
186
			continue
187
		case 'A' <= ch && ch <= 'Z':
188
			continue
189
		case 'a' <= ch && ch <= 'z':
190
			continue
191
		default:
192
			return true
193
		}
194
	}
195
	return false
196
}
197

198
// isAny reports whether sv is a google.protobuf.Any message
199
func isAny(sv reflect.Value) bool {
200
	type wkt interface {
201
		XXX_WellKnownType() string
202
	}
203
	t, ok := sv.Addr().Interface().(wkt)
204
	return ok && t.XXX_WellKnownType() == "Any"
205
}
206

207
// writeProto3Any writes an expanded google.protobuf.Any message.
208
//
209
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
210
// required messages are not linked in).
211
//
212
// It returns (true, error) when sv was written in expanded format or an error
213
// was encountered.
214
func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
215
	turl := sv.FieldByName("TypeUrl")
216
	val := sv.FieldByName("Value")
217
	if !turl.IsValid() || !val.IsValid() {
218
		return true, errors.New("proto: invalid google.protobuf.Any message")
219
	}
220

221
	b, ok := val.Interface().([]byte)
222
	if !ok {
223
		return true, errors.New("proto: invalid google.protobuf.Any message")
224
	}
225

226
	parts := strings.Split(turl.String(), "/")
227
	mt := MessageType(parts[len(parts)-1])
228
	if mt == nil {
229
		return false, nil
230
	}
231
	m := reflect.New(mt.Elem())
232
	if err := Unmarshal(b, m.Interface().(Message)); err != nil {
233
		return false, nil
234
	}
235
	w.Write([]byte("["))
236
	u := turl.String()
237
	if requiresQuotes(u) {
238
		writeString(w, u)
239
	} else {
240
		w.Write([]byte(u))
241
	}
242
	if w.compact {
243
		w.Write([]byte("]:<"))
244
	} else {
245
		w.Write([]byte("]: <\n"))
246
		w.ind++
247
	}
248
	if err := tm.writeStruct(w, m.Elem()); err != nil {
249
		return true, err
250
	}
251
	if w.compact {
252
		w.Write([]byte("> "))
253
	} else {
254
		w.ind--
255
		w.Write([]byte(">\n"))
256
	}
257
	return true, nil
258
}
259

260
func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
261
	if tm.ExpandAny && isAny(sv) {
262
		if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
263
			return err
264
		}
265
	}
266
	st := sv.Type()
267
	sprops := GetProperties(st)
268
	for i := 0; i < sv.NumField(); i++ {
269
		fv := sv.Field(i)
270
		props := sprops.Prop[i]
271
		name := st.Field(i).Name
272

273
		if name == "XXX_NoUnkeyedLiteral" {
274
			continue
275
		}
276

277
		if strings.HasPrefix(name, "XXX_") {
278
			// There are two XXX_ fields:
279
			//   XXX_unrecognized []byte
280
			//   XXX_extensions   map[int32]proto.Extension
281
			// The first is handled here;
282
			// the second is handled at the bottom of this function.
283
			if name == "XXX_unrecognized" && !fv.IsNil() {
284
				if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
285
					return err
286
				}
287
			}
288
			continue
289
		}
290
		if fv.Kind() == reflect.Ptr && fv.IsNil() {
291
			// Field not filled in. This could be an optional field or
292
			// a required field that wasn't filled in. Either way, there
293
			// isn't anything we can show for it.
294
			continue
295
		}
296
		if fv.Kind() == reflect.Slice && fv.IsNil() {
297
			// Repeated field that is empty, or a bytes field that is unused.
298
			continue
299
		}
300

301
		if props.Repeated && fv.Kind() == reflect.Slice {
302
			// Repeated field.
303
			for j := 0; j < fv.Len(); j++ {
304
				if err := writeName(w, props); err != nil {
305
					return err
306
				}
307
				if !w.compact {
308
					if err := w.WriteByte(' '); err != nil {
309
						return err
310
					}
311
				}
312
				v := fv.Index(j)
313
				if v.Kind() == reflect.Ptr && v.IsNil() {
314
					// A nil message in a repeated field is not valid,
315
					// but we can handle that more gracefully than panicking.
316
					if _, err := w.Write([]byte("<nil>\n")); err != nil {
317
						return err
318
					}
319
					continue
320
				}
321
				if len(props.Enum) > 0 {
322
					if err := tm.writeEnum(w, v, props); err != nil {
323
						return err
324
					}
325
				} else if err := tm.writeAny(w, v, props); err != nil {
326
					return err
327
				}
328
				if err := w.WriteByte('\n'); err != nil {
329
					return err
330
				}
331
			}
332
			continue
333
		}
334
		if fv.Kind() == reflect.Map {
335
			// Map fields are rendered as a repeated struct with key/value fields.
336
			keys := fv.MapKeys()
337
			sort.Sort(mapKeys(keys))
338
			for _, key := range keys {
339
				val := fv.MapIndex(key)
340
				if err := writeName(w, props); err != nil {
341
					return err
342
				}
343
				if !w.compact {
344
					if err := w.WriteByte(' '); err != nil {
345
						return err
346
					}
347
				}
348
				// open struct
349
				if err := w.WriteByte('<'); err != nil {
350
					return err
351
				}
352
				if !w.compact {
353
					if err := w.WriteByte('\n'); err != nil {
354
						return err
355
					}
356
				}
357
				w.indent()
358
				// key
359
				if _, err := w.WriteString("key:"); err != nil {
360
					return err
361
				}
362
				if !w.compact {
363
					if err := w.WriteByte(' '); err != nil {
364
						return err
365
					}
366
				}
367
				if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
368
					return err
369
				}
370
				if err := w.WriteByte('\n'); err != nil {
371
					return err
372
				}
373
				// nil values aren't legal, but we can avoid panicking because of them.
374
				if val.Kind() != reflect.Ptr || !val.IsNil() {
375
					// value
376
					if _, err := w.WriteString("value:"); err != nil {
377
						return err
378
					}
379
					if !w.compact {
380
						if err := w.WriteByte(' '); err != nil {
381
							return err
382
						}
383
					}
384
					if err := tm.writeAny(w, val, props.MapValProp); err != nil {
385
						return err
386
					}
387
					if err := w.WriteByte('\n'); err != nil {
388
						return err
389
					}
390
				}
391
				// close struct
392
				w.unindent()
393
				if err := w.WriteByte('>'); err != nil {
394
					return err
395
				}
396
				if err := w.WriteByte('\n'); err != nil {
397
					return err
398
				}
399
			}
400
			continue
401
		}
402
		if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
403
			// empty bytes field
404
			continue
405
		}
406
		if props.proto3 && fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
407
			// proto3 non-repeated scalar field; skip if zero value
408
			if isProto3Zero(fv) {
409
				continue
410
			}
411
		}
412

413
		if fv.Kind() == reflect.Interface {
414
			// Check if it is a oneof.
415
			if st.Field(i).Tag.Get("protobuf_oneof") != "" {
416
				// fv is nil, or holds a pointer to generated struct.
417
				// That generated struct has exactly one field,
418
				// which has a protobuf struct tag.
419
				if fv.IsNil() {
420
					continue
421
				}
422
				inner := fv.Elem().Elem() // interface -> *T -> T
423
				tag := inner.Type().Field(0).Tag.Get("protobuf")
424
				props = new(Properties) // Overwrite the outer props var, but not its pointee.
425
				props.Parse(tag)
426
				// Write the value in the oneof, not the oneof itself.
427
				fv = inner.Field(0)
428

429
				// Special case to cope with malformed messages gracefully:
430
				// If the value in the oneof is a nil pointer, don't panic
431
				// in writeAny.
432
				if fv.Kind() == reflect.Ptr && fv.IsNil() {
433
					// Use errors.New so writeAny won't render quotes.
434
					msg := errors.New("/* nil */")
435
					fv = reflect.ValueOf(&msg).Elem()
436
				}
437
			}
438
		}
439

440
		if err := writeName(w, props); err != nil {
441
			return err
442
		}
443
		if !w.compact {
444
			if err := w.WriteByte(' '); err != nil {
445
				return err
446
			}
447
		}
448

449
		if len(props.Enum) > 0 {
450
			if err := tm.writeEnum(w, fv, props); err != nil {
451
				return err
452
			}
453
		} else if err := tm.writeAny(w, fv, props); err != nil {
454
			return err
455
		}
456

457
		if err := w.WriteByte('\n'); err != nil {
458
			return err
459
		}
460
	}
461

462
	// Extensions (the XXX_extensions field).
463
	pv := sv
464
	if pv.CanAddr() {
465
		pv = sv.Addr()
466
	} else {
467
		pv = reflect.New(sv.Type())
468
		pv.Elem().Set(sv)
469
	}
470
	if _, err := extendable(pv.Interface()); err == nil {
471
		if err := tm.writeExtensions(w, pv); err != nil {
472
			return err
473
		}
474
	}
475

476
	return nil
477
}
478

479
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
480

481
// writeAny writes an arbitrary field.
482
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
483
	v = reflect.Indirect(v)
484

485
	if props != nil {
486
		if len(props.CustomType) > 0 {
487
			custom, ok := v.Interface().(Marshaler)
488
			if ok {
489
				data, err := custom.Marshal()
490
				if err != nil {
491
					return err
492
				}
493
				if err := writeString(w, string(data)); err != nil {
494
					return err
495
				}
496
				return nil
497
			}
498
		} else if len(props.CastType) > 0 {
499
			if _, ok := v.Interface().(interface {
500
				String() string
501
			}); ok {
502
				switch v.Kind() {
503
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
504
					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
505
					_, err := fmt.Fprintf(w, "%d", v.Interface())
506
					return err
507
				}
508
			}
509
		} else if props.StdTime {
510
			t, ok := v.Interface().(time.Time)
511
			if !ok {
512
				return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface())
513
			}
514
			tproto, err := timestampProto(t)
515
			if err != nil {
516
				return err
517
			}
518
			propsCopy := *props // Make a copy so that this is goroutine-safe
519
			propsCopy.StdTime = false
520
			err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy)
521
			return err
522
		} else if props.StdDuration {
523
			d, ok := v.Interface().(time.Duration)
524
			if !ok {
525
				return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface())
526
			}
527
			dproto := durationProto(d)
528
			propsCopy := *props // Make a copy so that this is goroutine-safe
529
			propsCopy.StdDuration = false
530
			err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy)
531
			return err
532
		}
533
	}
534

535
	// Floats have special cases.
536
	if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
537
		x := v.Float()
538
		var b []byte
539
		switch {
540
		case math.IsInf(x, 1):
541
			b = posInf
542
		case math.IsInf(x, -1):
543
			b = negInf
544
		case math.IsNaN(x):
545
			b = nan
546
		}
547
		if b != nil {
548
			_, err := w.Write(b)
549
			return err
550
		}
551
		// Other values are handled below.
552
	}
553

554
	// We don't attempt to serialise every possible value type; only those
555
	// that can occur in protocol buffers.
556
	switch v.Kind() {
557
	case reflect.Slice:
558
		// Should only be a []byte; repeated fields are handled in writeStruct.
559
		if err := writeString(w, string(v.Bytes())); err != nil {
560
			return err
561
		}
562
	case reflect.String:
563
		if err := writeString(w, v.String()); err != nil {
564
			return err
565
		}
566
	case reflect.Struct:
567
		// Required/optional group/message.
568
		var bra, ket byte = '<', '>'
569
		if props != nil && props.Wire == "group" {
570
			bra, ket = '{', '}'
571
		}
572
		if err := w.WriteByte(bra); err != nil {
573
			return err
574
		}
575
		if !w.compact {
576
			if err := w.WriteByte('\n'); err != nil {
577
				return err
578
			}
579
		}
580
		w.indent()
581
		if v.CanAddr() {
582
			// Calling v.Interface on a struct causes the reflect package to
583
			// copy the entire struct. This is racy with the new Marshaler
584
			// since we atomically update the XXX_sizecache.
585
			//
586
			// Thus, we retrieve a pointer to the struct if possible to avoid
587
			// a race since v.Interface on the pointer doesn't copy the struct.
588
			//
589
			// If v is not addressable, then we are not worried about a race
590
			// since it implies that the binary Marshaler cannot possibly be
591
			// mutating this value.
592
			v = v.Addr()
593
		}
594
		if v.Type().Implements(textMarshalerType) {
595
			text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
596
			if err != nil {
597
				return err
598
			}
599
			if _, err = w.Write(text); err != nil {
600
				return err
601
			}
602
		} else {
603
			if v.Kind() == reflect.Ptr {
604
				v = v.Elem()
605
			}
606
			if err := tm.writeStruct(w, v); err != nil {
607
				return err
608
			}
609
		}
610
		w.unindent()
611
		if err := w.WriteByte(ket); err != nil {
612
			return err
613
		}
614
	default:
615
		_, err := fmt.Fprint(w, v.Interface())
616
		return err
617
	}
618
	return nil
619
}
620

621
// equivalent to C's isprint.
622
func isprint(c byte) bool {
623
	return c >= 0x20 && c < 0x7f
624
}
625

626
// writeString writes a string in the protocol buffer text format.
627
// It is similar to strconv.Quote except we don't use Go escape sequences,
628
// we treat the string as a byte sequence, and we use octal escapes.
629
// These differences are to maintain interoperability with the other
630
// languages' implementations of the text format.
631
func writeString(w *textWriter, s string) error {
632
	// use WriteByte here to get any needed indent
633
	if err := w.WriteByte('"'); err != nil {
634
		return err
635
	}
636
	// Loop over the bytes, not the runes.
637
	for i := 0; i < len(s); i++ {
638
		var err error
639
		// Divergence from C++: we don't escape apostrophes.
640
		// There's no need to escape them, and the C++ parser
641
		// copes with a naked apostrophe.
642
		switch c := s[i]; c {
643
		case '\n':
644
			_, err = w.w.Write(backslashN)
645
		case '\r':
646
			_, err = w.w.Write(backslashR)
647
		case '\t':
648
			_, err = w.w.Write(backslashT)
649
		case '"':
650
			_, err = w.w.Write(backslashDQ)
651
		case '\\':
652
			_, err = w.w.Write(backslashBS)
653
		default:
654
			if isprint(c) {
655
				err = w.w.WriteByte(c)
656
			} else {
657
				_, err = fmt.Fprintf(w.w, "\\%03o", c)
658
			}
659
		}
660
		if err != nil {
661
			return err
662
		}
663
	}
664
	return w.WriteByte('"')
665
}
666

667
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
668
	if !w.compact {
669
		if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
670
			return err
671
		}
672
	}
673
	b := NewBuffer(data)
674
	for b.index < len(b.buf) {
675
		x, err := b.DecodeVarint()
676
		if err != nil {
677
			_, ferr := fmt.Fprintf(w, "/* %v */\n", err)
678
			return ferr
679
		}
680
		wire, tag := x&7, x>>3
681
		if wire == WireEndGroup {
682
			w.unindent()
683
			if _, werr := w.Write(endBraceNewline); werr != nil {
684
				return werr
685
			}
686
			continue
687
		}
688
		if _, ferr := fmt.Fprint(w, tag); ferr != nil {
689
			return ferr
690
		}
691
		if wire != WireStartGroup {
692
			if err = w.WriteByte(':'); err != nil {
693
				return err
694
			}
695
		}
696
		if !w.compact || wire == WireStartGroup {
697
			if err = w.WriteByte(' '); err != nil {
698
				return err
699
			}
700
		}
701
		switch wire {
702
		case WireBytes:
703
			buf, e := b.DecodeRawBytes(false)
704
			if e == nil {
705
				_, err = fmt.Fprintf(w, "%q", buf)
706
			} else {
707
				_, err = fmt.Fprintf(w, "/* %v */", e)
708
			}
709
		case WireFixed32:
710
			x, err = b.DecodeFixed32()
711
			err = writeUnknownInt(w, x, err)
712
		case WireFixed64:
713
			x, err = b.DecodeFixed64()
714
			err = writeUnknownInt(w, x, err)
715
		case WireStartGroup:
716
			err = w.WriteByte('{')
717
			w.indent()
718
		case WireVarint:
719
			x, err = b.DecodeVarint()
720
			err = writeUnknownInt(w, x, err)
721
		default:
722
			_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
723
		}
724
		if err != nil {
725
			return err
726
		}
727
		if err := w.WriteByte('\n'); err != nil {
728
			return err
729
		}
730
	}
731
	return nil
732
}
733

734
func writeUnknownInt(w *textWriter, x uint64, err error) error {
735
	if err == nil {
736
		_, err = fmt.Fprint(w, x)
737
	} else {
738
		_, err = fmt.Fprintf(w, "/* %v */", err)
739
	}
740
	return err
741
}
742

743
type int32Slice []int32
744

745
func (s int32Slice) Len() int           { return len(s) }
746
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
747
func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
748

749
// writeExtensions writes all the extensions in pv.
750
// pv is assumed to be a pointer to a protocol message struct that is extendable.
751
func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
752
	emap := extensionMaps[pv.Type().Elem()]
753
	e := pv.Interface().(Message)
754

755
	var m map[int32]Extension
756
	var mu sync.Locker
757
	if em, ok := e.(extensionsBytes); ok {
758
		eb := em.GetExtensions()
759
		var err error
760
		m, err = BytesToExtensionsMap(*eb)
761
		if err != nil {
762
			return err
763
		}
764
		mu = notLocker{}
765
	} else if _, ok := e.(extendableProto); ok {
766
		ep, _ := extendable(e)
767
		m, mu = ep.extensionsRead()
768
		if m == nil {
769
			return nil
770
		}
771
	}
772

773
	// Order the extensions by ID.
774
	// This isn't strictly necessary, but it will give us
775
	// canonical output, which will also make testing easier.
776

777
	mu.Lock()
778
	ids := make([]int32, 0, len(m))
779
	for id := range m {
780
		ids = append(ids, id)
781
	}
782
	sort.Sort(int32Slice(ids))
783
	mu.Unlock()
784

785
	for _, extNum := range ids {
786
		ext := m[extNum]
787
		var desc *ExtensionDesc
788
		if emap != nil {
789
			desc = emap[extNum]
790
		}
791
		if desc == nil {
792
			// Unknown extension.
793
			if err := writeUnknownStruct(w, ext.enc); err != nil {
794
				return err
795
			}
796
			continue
797
		}
798

799
		pb, err := GetExtension(e, desc)
800
		if err != nil {
801
			return fmt.Errorf("failed getting extension: %v", err)
802
		}
803

804
		// Repeated extensions will appear as a slice.
805
		if !desc.repeated() {
806
			if err := tm.writeExtension(w, desc.Name, pb); err != nil {
807
				return err
808
			}
809
		} else {
810
			v := reflect.ValueOf(pb)
811
			for i := 0; i < v.Len(); i++ {
812
				if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
813
					return err
814
				}
815
			}
816
		}
817
	}
818
	return nil
819
}
820

821
func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
822
	if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
823
		return err
824
	}
825
	if !w.compact {
826
		if err := w.WriteByte(' '); err != nil {
827
			return err
828
		}
829
	}
830
	if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
831
		return err
832
	}
833
	if err := w.WriteByte('\n'); err != nil {
834
		return err
835
	}
836
	return nil
837
}
838

839
func (w *textWriter) writeIndent() {
840
	if !w.complete {
841
		return
842
	}
843
	remain := w.ind * 2
844
	for remain > 0 {
845
		n := remain
846
		if n > len(spaces) {
847
			n = len(spaces)
848
		}
849
		w.w.Write(spaces[:n])
850
		remain -= n
851
	}
852
	w.complete = false
853
}
854

855
// TextMarshaler is a configurable text format marshaler.
856
type TextMarshaler struct {
857
	Compact   bool // use compact text format (one line).
858
	ExpandAny bool // expand google.protobuf.Any messages of known types
859
}
860

861
// Marshal writes a given protocol buffer in text format.
862
// The only errors returned are from w.
863
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
864
	val := reflect.ValueOf(pb)
865
	if pb == nil || val.IsNil() {
866
		w.Write([]byte("<nil>"))
867
		return nil
868
	}
869
	var bw *bufio.Writer
870
	ww, ok := w.(writer)
871
	if !ok {
872
		bw = bufio.NewWriter(w)
873
		ww = bw
874
	}
875
	aw := &textWriter{
876
		w:        ww,
877
		complete: true,
878
		compact:  tm.Compact,
879
	}
880

881
	if etm, ok := pb.(encoding.TextMarshaler); ok {
882
		text, err := etm.MarshalText()
883
		if err != nil {
884
			return err
885
		}
886
		if _, err = aw.Write(text); err != nil {
887
			return err
888
		}
889
		if bw != nil {
890
			return bw.Flush()
891
		}
892
		return nil
893
	}
894
	// Dereference the received pointer so we don't have outer < and >.
895
	v := reflect.Indirect(val)
896
	if err := tm.writeStruct(aw, v); err != nil {
897
		return err
898
	}
899
	if bw != nil {
900
		return bw.Flush()
901
	}
902
	return nil
903
}
904

905
// Text is the same as Marshal, but returns the string directly.
906
func (tm *TextMarshaler) Text(pb Message) string {
907
	var buf bytes.Buffer
908
	tm.Marshal(&buf, pb)
909
	return buf.String()
910
}
911

912
var (
913
	defaultTextMarshaler = TextMarshaler{}
914
	compactTextMarshaler = TextMarshaler{Compact: true}
915
)
916

917
// TODO: consider removing some of the Marshal functions below.
918

919
// MarshalText writes a given protocol buffer in text format.
920
// The only errors returned are from w.
921
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
922

923
// MarshalTextString is the same as MarshalText, but returns the string directly.
924
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
925

926
// CompactText writes a given protocol buffer in compact text format (one line).
927
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
928

929
// CompactTextString is the same as CompactText, but returns the string directly.
930
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
931

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

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

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

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