1// 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
5// Package protopack enables manual encoding and decoding of protobuf wire data.
6//
7// This package is intended for use in debugging and/or creation of test data.
8// Proper usage of this package requires knowledge of the wire format.
9//
10// See https://developers.google.com/protocol-buffers/docs/encoding.
11package protopack
12
13import (
14	"fmt"
15	"io"
16	"math"
17	"path"
18	"reflect"
19	"strconv"
20	"strings"
21	"unicode"
22	"unicode/utf8"
23
24	"google.golang.org/protobuf/encoding/protowire"
25	"google.golang.org/protobuf/reflect/protoreflect"
26)
27
28// Number is the field number; aliased from the protowire package for convenience.
29type Number = protowire.Number
30
31// Number type constants; copied from the protowire package for convenience.
32const (
33	MinValidNumber      Number = protowire.MinValidNumber
34	FirstReservedNumber Number = protowire.FirstReservedNumber
35	LastReservedNumber  Number = protowire.LastReservedNumber
36	MaxValidNumber      Number = protowire.MaxValidNumber
37)
38
39// Type is the wire type; aliased from the protowire package for convenience.
40type Type = protowire.Type
41
42// Wire type constants; copied from the protowire package for convenience.
43const (
44	VarintType     Type = protowire.VarintType
45	Fixed32Type    Type = protowire.Fixed32Type
46	Fixed64Type    Type = protowire.Fixed64Type
47	BytesType      Type = protowire.BytesType
48	StartGroupType Type = protowire.StartGroupType
49	EndGroupType   Type = protowire.EndGroupType
50)
51
52type (
53	// Token is any other type (e.g., Message, Tag, Varint, Float32, etc).
54	Token token
55	// Message is an ordered sequence of  Tokens, where certain tokens may
56	// contain other tokens. It is functionally a concrete syntax tree that
57	// losslessly represents any arbitrary wire data (including invalid input).
58	Message []Token
59
60	// Tag is a tuple of the field number and the wire type.
61	Tag struct {
62		Number Number
63		Type   Type
64	}
65	// Bool is a boolean.
66	Bool bool
67	// Varint is a signed varint using 64-bit two's complement encoding.
68	Varint int64
69	// Svarint is a signed varint using zig-zag encoding.
70	Svarint int64
71	// Uvarint is a unsigned varint.
72	Uvarint uint64
73
74	// Int32 is a signed 32-bit fixed-width integer.
75	Int32 int32
76	// Uint32 is an unsigned 32-bit fixed-width integer.
77	Uint32 uint32
78	// Float32 is a 32-bit fixed-width floating point number.
79	Float32 float32
80
81	// Int64 is a signed 64-bit fixed-width integer.
82	Int64 int64
83	// Uint64 is an unsigned 64-bit fixed-width integer.
84	Uint64 uint64
85	// Float64 is a 64-bit fixed-width floating point number.
86	Float64 float64
87
88	// String is a length-prefixed string.
89	String string
90	// Bytes is a length-prefixed bytes.
91	Bytes []byte
92	// LengthPrefix is a length-prefixed message.
93	LengthPrefix Message
94
95	// Denormalized is a denormalized varint value, where a varint is encoded
96	// using more bytes than is strictly necessary. The number of extra bytes
97	// alone is sufficient to losslessly represent the denormalized varint.
98	//
99	// The value may be one of Tag, Bool, Varint, Svarint, or Uvarint,
100	// where the varint representation of each token is denormalized.
101	//
102	// Alternatively, the value may be one of String, Bytes, or LengthPrefix,
103	// where the varint representation of the length-prefix is denormalized.
104	Denormalized struct {
105		Count uint // number of extra bytes
106		Value Token
107	}
108
109	// Raw are bytes directly appended to output.
110	Raw []byte
111)
112
113type token interface {
114	isToken()
115}
116
117func (Message) isToken()      {}
118func (Tag) isToken()          {}
119func (Bool) isToken()         {}
120func (Varint) isToken()       {}
121func (Svarint) isToken()      {}
122func (Uvarint) isToken()      {}
123func (Int32) isToken()        {}
124func (Uint32) isToken()       {}
125func (Float32) isToken()      {}
126func (Int64) isToken()        {}
127func (Uint64) isToken()       {}
128func (Float64) isToken()      {}
129func (String) isToken()       {}
130func (Bytes) isToken()        {}
131func (LengthPrefix) isToken() {}
132func (Denormalized) isToken() {}
133func (Raw) isToken()          {}
134
135// Size reports the size in bytes of the marshaled message.
136func (m Message) Size() int {
137	var n int
138	for _, v := range m {
139		switch v := v.(type) {
140		case Message:
141			n += v.Size()
142		case Tag:
143			n += protowire.SizeTag(v.Number)
144		case Bool:
145			n += protowire.SizeVarint(protowire.EncodeBool(false))
146		case Varint:
147			n += protowire.SizeVarint(uint64(v))
148		case Svarint:
149			n += protowire.SizeVarint(protowire.EncodeZigZag(int64(v)))
150		case Uvarint:
151			n += protowire.SizeVarint(uint64(v))
152		case Int32, Uint32, Float32:
153			n += protowire.SizeFixed32()
154		case Int64, Uint64, Float64:
155			n += protowire.SizeFixed64()
156		case String:
157			n += protowire.SizeBytes(len(v))
158		case Bytes:
159			n += protowire.SizeBytes(len(v))
160		case LengthPrefix:
161			n += protowire.SizeBytes(Message(v).Size())
162		case Denormalized:
163			n += int(v.Count) + Message{v.Value}.Size()
164		case Raw:
165			n += len(v)
166		default:
167			panic(fmt.Sprintf("unknown type: %T", v))
168		}
169	}
170	return n
171}
172
173// Marshal encodes a syntax tree into the protobuf wire format.
174//
175// Example message definition:
176//	message MyMessage {
177//		string field1 = 1;
178//		int64 field2 = 2;
179//		repeated float32 field3 = 3;
180//	}
181//
182// Example encoded message:
183//	b := Message{
184//		Tag{1, BytesType}, String("Hello, world!"),
185//		Tag{2, VarintType}, Varint(-10),
186//		Tag{3, BytesType}, LengthPrefix{
187//			Float32(1.1), Float32(2.2), Float32(3.3),
188//		},
189//	}.Marshal()
190//
191// Resulting wire data:
192//	0x0000  0a 0d 48 65 6c 6c 6f 2c  20 77 6f 72 6c 64 21 10  |..Hello, world!.|
193//	0x0010  f6 ff ff ff ff ff ff ff  ff 01 1a 0c cd cc 8c 3f  |...............?|
194//	0x0020  cd cc 0c 40 33 33 53 40                           |...@33S@|
195func (m Message) Marshal() []byte {
196	var out []byte
197	for _, v := range m {
198		switch v := v.(type) {
199		case Message:
200			out = append(out, v.Marshal()...)
201		case Tag:
202			out = protowire.AppendTag(out, v.Number, v.Type)
203		case Bool:
204			out = protowire.AppendVarint(out, protowire.EncodeBool(bool(v)))
205		case Varint:
206			out = protowire.AppendVarint(out, uint64(v))
207		case Svarint:
208			out = protowire.AppendVarint(out, protowire.EncodeZigZag(int64(v)))
209		case Uvarint:
210			out = protowire.AppendVarint(out, uint64(v))
211		case Int32:
212			out = protowire.AppendFixed32(out, uint32(v))
213		case Uint32:
214			out = protowire.AppendFixed32(out, uint32(v))
215		case Float32:
216			out = protowire.AppendFixed32(out, math.Float32bits(float32(v)))
217		case Int64:
218			out = protowire.AppendFixed64(out, uint64(v))
219		case Uint64:
220			out = protowire.AppendFixed64(out, uint64(v))
221		case Float64:
222			out = protowire.AppendFixed64(out, math.Float64bits(float64(v)))
223		case String:
224			out = protowire.AppendBytes(out, []byte(v))
225		case Bytes:
226			out = protowire.AppendBytes(out, []byte(v))
227		case LengthPrefix:
228			out = protowire.AppendBytes(out, Message(v).Marshal())
229		case Denormalized:
230			b := Message{v.Value}.Marshal()
231			_, n := protowire.ConsumeVarint(b)
232			out = append(out, b[:n]...)
233			for i := uint(0); i < v.Count; i++ {
234				out[len(out)-1] |= 0x80 // set continuation bit on previous
235				out = append(out, 0)
236			}
237			out = append(out, b[n:]...)
238		case Raw:
239			return append(out, v...)
240		default:
241			panic(fmt.Sprintf("unknown type: %T", v))
242		}
243	}
244	return out
245}
246
247// Unmarshal parses the input protobuf wire data as a syntax tree.
248// Any parsing error results in the remainder of the input being
249// concatenated to the message as a Raw type.
250//
251// Each tag (a tuple of the field number and wire type) encountered is
252// inserted into the syntax tree as a Tag.
253//
254// The contents of each wire type is mapped to the following Go types:
255//	VarintType   => Uvarint
256//	Fixed32Type  => Uint32
257//	Fixed64Type  => Uint64
258//	BytesType    => Bytes
259//	GroupType    => Message
260//
261// Since the wire format is not self-describing, this function cannot parse
262// sub-messages and will leave them as the Bytes type. Further manual parsing
263// can be performed as such:
264//	var m, m1, m2 Message
265//	m.Unmarshal(b)
266//	m1.Unmarshal(m[3].(Bytes))
267//	m[3] = LengthPrefix(m1)
268//	m2.Unmarshal(m[3].(LengthPrefix)[1].(Bytes))
269//	m[3].(LengthPrefix)[1] = LengthPrefix(m2)
270//
271// Unmarshal is useful for debugging the protobuf wire format.
272func (m *Message) Unmarshal(in []byte) {
273	m.unmarshal(in, nil, false)
274}
275
276// UnmarshalDescriptor parses the input protobuf wire data as a syntax tree
277// using the provided message descriptor for more accurate parsing of fields.
278// It operates like Unmarshal, but may use a wider range of Go types to
279// represent the wire data.
280//
281// The contents of each wire type is mapped to one of the following Go types:
282//	VarintType   => Bool, Varint, Svarint, Uvarint
283//	Fixed32Type  => Int32, Uint32, Float32
284//	Fixed64Type  => Uint32, Uint64, Float64
285//	BytesType    => String, Bytes, LengthPrefix
286//	GroupType    => Message
287//
288// If the field is unknown, it uses the same mapping as Unmarshal.
289// Known sub-messages are parsed as a Message and packed repeated fields are
290// parsed as a LengthPrefix.
291func (m *Message) UnmarshalDescriptor(in []byte, desc protoreflect.MessageDescriptor) {
292	m.unmarshal(in, desc, false)
293}
294
295// UnmarshalAbductive is like UnmarshalDescriptor, but infers abductively
296// whether any unknown bytes values is a message based on whether it is
297// a syntactically well-formed message.
298//
299// Note that the protobuf wire format is not fully self-describing,
300// so abductive inference may attempt to expand a bytes value as a message
301// that is not actually a message. It is a best-effort guess.
302func (m *Message) UnmarshalAbductive(in []byte, desc protoreflect.MessageDescriptor) {
303	m.unmarshal(in, desc, true)
304}
305
306func (m *Message) unmarshal(in []byte, desc protoreflect.MessageDescriptor, inferMessage bool) {
307	p := parser{in: in, out: *m}
308	p.parseMessage(desc, false, inferMessage)
309	*m = p.out
310}
311
312type parser struct {
313	in  []byte
314	out []Token
315
316	invalid bool
317}
318
319func (p *parser) parseMessage(msgDesc protoreflect.MessageDescriptor, group, inferMessage bool) {
320	for len(p.in) > 0 {
321		v, n := protowire.ConsumeVarint(p.in)
322		num, typ := protowire.DecodeTag(v)
323		if n < 0 || num <= 0 || v > math.MaxUint32 {
324			p.out, p.in = append(p.out, Raw(p.in)), nil
325			p.invalid = true
326			return
327		}
328		if typ == EndGroupType && group {
329			return // if inside a group, then stop
330		}
331		p.out, p.in = append(p.out, Tag{num, typ}), p.in[n:]
332		if m := n - protowire.SizeVarint(v); m > 0 {
333			p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
334		}
335
336		// If descriptor is available, use it for more accurate parsing.
337		var isPacked bool
338		var kind protoreflect.Kind
339		var subDesc protoreflect.MessageDescriptor
340		if msgDesc != nil && !msgDesc.IsPlaceholder() {
341			if fieldDesc := msgDesc.Fields().ByNumber(num); fieldDesc != nil {
342				isPacked = fieldDesc.IsPacked()
343				kind = fieldDesc.Kind()
344				switch kind {
345				case protoreflect.MessageKind, protoreflect.GroupKind:
346					subDesc = fieldDesc.Message()
347					if subDesc == nil || subDesc.IsPlaceholder() {
348						kind = 0
349					}
350				}
351			}
352		}
353
354		switch typ {
355		case VarintType:
356			p.parseVarint(kind)
357		case Fixed32Type:
358			p.parseFixed32(kind)
359		case Fixed64Type:
360			p.parseFixed64(kind)
361		case BytesType:
362			p.parseBytes(isPacked, kind, subDesc, inferMessage)
363		case StartGroupType:
364			p.parseGroup(num, subDesc, inferMessage)
365		case EndGroupType:
366			// Handled by p.parseGroup.
367		default:
368			p.out, p.in = append(p.out, Raw(p.in)), nil
369			p.invalid = true
370		}
371	}
372}
373
374func (p *parser) parseVarint(kind protoreflect.Kind) {
375	v, n := protowire.ConsumeVarint(p.in)
376	if n < 0 {
377		p.out, p.in = append(p.out, Raw(p.in)), nil
378		p.invalid = true
379		return
380	}
381	switch kind {
382	case protoreflect.BoolKind:
383		switch v {
384		case 0:
385			p.out, p.in = append(p.out, Bool(false)), p.in[n:]
386		case 1:
387			p.out, p.in = append(p.out, Bool(true)), p.in[n:]
388		default:
389			p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
390		}
391	case protoreflect.Int32Kind, protoreflect.Int64Kind:
392		p.out, p.in = append(p.out, Varint(v)), p.in[n:]
393	case protoreflect.Sint32Kind, protoreflect.Sint64Kind:
394		p.out, p.in = append(p.out, Svarint(protowire.DecodeZigZag(v))), p.in[n:]
395	default:
396		p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
397	}
398	if m := n - protowire.SizeVarint(v); m > 0 {
399		p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
400	}
401}
402
403func (p *parser) parseFixed32(kind protoreflect.Kind) {
404	v, n := protowire.ConsumeFixed32(p.in)
405	if n < 0 {
406		p.out, p.in = append(p.out, Raw(p.in)), nil
407		p.invalid = true
408		return
409	}
410	switch kind {
411	case protoreflect.FloatKind:
412		p.out, p.in = append(p.out, Float32(math.Float32frombits(v))), p.in[n:]
413	case protoreflect.Sfixed32Kind:
414		p.out, p.in = append(p.out, Int32(v)), p.in[n:]
415	default:
416		p.out, p.in = append(p.out, Uint32(v)), p.in[n:]
417	}
418}
419
420func (p *parser) parseFixed64(kind protoreflect.Kind) {
421	v, n := protowire.ConsumeFixed64(p.in)
422	if n < 0 {
423		p.out, p.in = append(p.out, Raw(p.in)), nil
424		p.invalid = true
425		return
426	}
427	switch kind {
428	case protoreflect.DoubleKind:
429		p.out, p.in = append(p.out, Float64(math.Float64frombits(v))), p.in[n:]
430	case protoreflect.Sfixed64Kind:
431		p.out, p.in = append(p.out, Int64(v)), p.in[n:]
432	default:
433		p.out, p.in = append(p.out, Uint64(v)), p.in[n:]
434	}
435}
436
437func (p *parser) parseBytes(isPacked bool, kind protoreflect.Kind, desc protoreflect.MessageDescriptor, inferMessage bool) {
438	v, n := protowire.ConsumeVarint(p.in)
439	if n < 0 {
440		p.out, p.in = append(p.out, Raw(p.in)), nil
441		p.invalid = true
442		return
443	}
444	p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
445	if m := n - protowire.SizeVarint(v); m > 0 {
446		p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
447	}
448	if v > uint64(len(p.in)) {
449		p.out, p.in = append(p.out, Raw(p.in)), nil
450		p.invalid = true
451		return
452	}
453	p.out = p.out[:len(p.out)-1] // subsequent tokens contain prefix-length
454
455	if isPacked {
456		p.parsePacked(int(v), kind)
457	} else {
458		switch kind {
459		case protoreflect.MessageKind:
460			p2 := parser{in: p.in[:v]}
461			p2.parseMessage(desc, false, inferMessage)
462			p.out, p.in = append(p.out, LengthPrefix(p2.out)), p.in[v:]
463		case protoreflect.StringKind:
464			p.out, p.in = append(p.out, String(p.in[:v])), p.in[v:]
465		case protoreflect.BytesKind:
466			p.out, p.in = append(p.out, Bytes(p.in[:v])), p.in[v:]
467		default:
468			if inferMessage {
469				// Check whether this is a syntactically valid message.
470				p2 := parser{in: p.in[:v]}
471				p2.parseMessage(nil, false, inferMessage)
472				if !p2.invalid {
473					p.out, p.in = append(p.out, LengthPrefix(p2.out)), p.in[v:]
474					break
475				}
476			}
477			p.out, p.in = append(p.out, Bytes(p.in[:v])), p.in[v:]
478		}
479	}
480	if m := n - protowire.SizeVarint(v); m > 0 {
481		p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
482	}
483}
484
485func (p *parser) parsePacked(n int, kind protoreflect.Kind) {
486	p2 := parser{in: p.in[:n]}
487	for len(p2.in) > 0 {
488		switch kind {
489		case protoreflect.BoolKind, protoreflect.EnumKind,
490			protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind,
491			protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind:
492			p2.parseVarint(kind)
493		case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind:
494			p2.parseFixed32(kind)
495		case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind:
496			p2.parseFixed64(kind)
497		default:
498			panic(fmt.Sprintf("invalid packed kind: %v", kind))
499		}
500	}
501	p.out, p.in = append(p.out, LengthPrefix(p2.out)), p.in[n:]
502}
503
504func (p *parser) parseGroup(startNum protowire.Number, desc protoreflect.MessageDescriptor, inferMessage bool) {
505	p2 := parser{in: p.in}
506	p2.parseMessage(desc, true, inferMessage)
507	if len(p2.out) > 0 {
508		p.out = append(p.out, Message(p2.out))
509	}
510	p.in = p2.in
511
512	// Append the trailing end group.
513	v, n := protowire.ConsumeVarint(p.in)
514	if endNum, typ := protowire.DecodeTag(v); typ == EndGroupType {
515		if startNum != endNum {
516			p.invalid = true
517		}
518		p.out, p.in = append(p.out, Tag{endNum, typ}), p.in[n:]
519		if m := n - protowire.SizeVarint(v); m > 0 {
520			p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
521		}
522	}
523}
524
525// Format implements a custom formatter to visualize the syntax tree.
526// Using "%#v" formats the Message in Go source code.
527func (m Message) Format(s fmt.State, r rune) {
528	switch r {
529	case 'x':
530		io.WriteString(s, fmt.Sprintf("%x", m.Marshal()))
531	case 'X':
532		io.WriteString(s, fmt.Sprintf("%X", m.Marshal()))
533	case 'v':
534		switch {
535		case s.Flag('#'):
536			io.WriteString(s, m.format(true, true))
537		case s.Flag('+'):
538			io.WriteString(s, m.format(false, true))
539		default:
540			io.WriteString(s, m.format(false, false))
541		}
542	default:
543		panic("invalid verb: " + string(r))
544	}
545}
546
547// format formats the message.
548// If source is enabled, this emits valid Go source.
549// If multi is enabled, the output may span multiple lines.
550func (m Message) format(source, multi bool) string {
551	var ss []string
552	var prefix, nextPrefix string
553	for _, v := range m {
554		// Ensure certain tokens have preceding or succeeding newlines.
555		prefix, nextPrefix = nextPrefix, " "
556		if multi {
557			switch v := v.(type) {
558			case Tag: // only has preceding newline
559				prefix = "\n"
560			case Denormalized: // only has preceding newline
561				if _, ok := v.Value.(Tag); ok {
562					prefix = "\n"
563				}
564			case Message, Raw: // has preceding and succeeding newlines
565				prefix, nextPrefix = "\n", "\n"
566			}
567		}
568
569		s := formatToken(v, source, multi)
570		ss = append(ss, prefix+s+",")
571	}
572
573	var s string
574	if len(ss) > 0 {
575		s = strings.TrimSpace(strings.Join(ss, ""))
576		if multi {
577			s = "\n\t" + strings.Join(strings.Split(s, "\n"), "\n\t") + "\n"
578		} else {
579			s = strings.TrimSuffix(s, ",")
580		}
581	}
582	s = fmt.Sprintf("%T{%s}", m, s)
583	if !source {
584		s = trimPackage(s)
585	}
586	return s
587}
588
589// formatToken formats a single token.
590func formatToken(t Token, source, multi bool) (s string) {
591	switch v := t.(type) {
592	case Message:
593		s = v.format(source, multi)
594	case LengthPrefix:
595		s = formatPacked(v, source, multi)
596		if s == "" {
597			ms := Message(v).format(source, multi)
598			s = fmt.Sprintf("%T(%s)", v, ms)
599		}
600	case Tag:
601		s = fmt.Sprintf("%T{%d, %s}", v, v.Number, formatType(v.Type, source))
602	case Bool, Varint, Svarint, Uvarint, Int32, Uint32, Float32, Int64, Uint64, Float64:
603		if source {
604			// Print floats in a way that preserves exact precision.
605			if f, _ := v.(Float32); math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) {
606				switch {
607				case f > 0:
608					s = fmt.Sprintf("%T(math.Inf(+1))", v)
609				case f < 0:
610					s = fmt.Sprintf("%T(math.Inf(-1))", v)
611				case math.Float32bits(float32(math.NaN())) == math.Float32bits(float32(f)):
612					s = fmt.Sprintf("%T(math.NaN())", v)
613				default:
614					s = fmt.Sprintf("%T(math.Float32frombits(0x%08x))", v, math.Float32bits(float32(f)))
615				}
616				break
617			}
618			if f, _ := v.(Float64); math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) {
619				switch {
620				case f > 0:
621					s = fmt.Sprintf("%T(math.Inf(+1))", v)
622				case f < 0:
623					s = fmt.Sprintf("%T(math.Inf(-1))", v)
624				case math.Float64bits(float64(math.NaN())) == math.Float64bits(float64(f)):
625					s = fmt.Sprintf("%T(math.NaN())", v)
626				default:
627					s = fmt.Sprintf("%T(math.Float64frombits(0x%016x))", v, math.Float64bits(float64(f)))
628				}
629				break
630			}
631		}
632		s = fmt.Sprintf("%T(%v)", v, v)
633	case String, Bytes, Raw:
634		s = fmt.Sprintf("%s", v)
635		s = fmt.Sprintf("%T(%s)", v, formatString(s))
636	case Denormalized:
637		s = fmt.Sprintf("%T{+%d, %v}", v, v.Count, formatToken(v.Value, source, multi))
638	default:
639		panic(fmt.Sprintf("unknown type: %T", v))
640	}
641	if !source {
642		s = trimPackage(s)
643	}
644	return s
645}
646
647// formatPacked returns a non-empty string if LengthPrefix looks like a packed
648// repeated field of primitives.
649func formatPacked(v LengthPrefix, source, multi bool) string {
650	var ss []string
651	for _, v := range v {
652		switch v.(type) {
653		case Bool, Varint, Svarint, Uvarint, Int32, Uint32, Float32, Int64, Uint64, Float64, Denormalized, Raw:
654			if v, ok := v.(Denormalized); ok {
655				switch v.Value.(type) {
656				case Bool, Varint, Svarint, Uvarint:
657				default:
658					return ""
659				}
660			}
661			ss = append(ss, formatToken(v, source, multi))
662		default:
663			return ""
664		}
665	}
666	s := fmt.Sprintf("%T{%s}", v, strings.Join(ss, ", "))
667	if !source {
668		s = trimPackage(s)
669	}
670	return s
671}
672
673// formatType returns the name for Type.
674func formatType(t Type, source bool) (s string) {
675	switch t {
676	case VarintType:
677		s = pkg + ".VarintType"
678	case Fixed32Type:
679		s = pkg + ".Fixed32Type"
680	case Fixed64Type:
681		s = pkg + ".Fixed64Type"
682	case BytesType:
683		s = pkg + ".BytesType"
684	case StartGroupType:
685		s = pkg + ".StartGroupType"
686	case EndGroupType:
687		s = pkg + ".EndGroupType"
688	default:
689		s = fmt.Sprintf("Type(%d)", t)
690	}
691	if !source {
692		s = strings.TrimSuffix(trimPackage(s), "Type")
693	}
694	return s
695}
696
697// formatString returns a quoted string for s.
698func formatString(s string) string {
699	// Use quoted string if it the same length as a raw string literal.
700	// Otherwise, attempt to use the raw string form.
701	qs := strconv.Quote(s)
702	if len(qs) == 1+len(s)+1 {
703		return qs
704	}
705
706	// Disallow newlines to ensure output is a single line.
707	// Disallow non-printable runes for readability purposes.
708	rawInvalid := func(r rune) bool {
709		return r == '`' || r == '\n' || r == utf8.RuneError || !unicode.IsPrint(r)
710	}
711	if strings.IndexFunc(s, rawInvalid) < 0 {
712		return "`" + s + "`"
713	}
714	return qs
715}
716
717var pkg = path.Base(reflect.TypeOf(Tag{}).PkgPath())
718
719func trimPackage(s string) string {
720	return strings.TrimPrefix(strings.TrimPrefix(s, pkg), ".")
721}
722