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.UnmarshalDescriptor(in, nil)
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	p := parser{in: in, out: *m}
293	p.parseMessage(desc, false)
294	*m = p.out
295}
296
297type parser struct {
298	in  []byte
299	out []Token
300}
301
302func (p *parser) parseMessage(msgDesc protoreflect.MessageDescriptor, group bool) {
303	for len(p.in) > 0 {
304		v, n := protowire.ConsumeVarint(p.in)
305		num, typ := protowire.DecodeTag(v)
306		if n < 0 || num < 0 || v > math.MaxUint32 {
307			p.out, p.in = append(p.out, Raw(p.in)), nil
308			return
309		}
310		if typ == EndGroupType && group {
311			return // if inside a group, then stop
312		}
313		p.out, p.in = append(p.out, Tag{num, typ}), p.in[n:]
314		if m := n - protowire.SizeVarint(v); m > 0 {
315			p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
316		}
317
318		// If descriptor is available, use it for more accurate parsing.
319		var isPacked bool
320		var kind protoreflect.Kind
321		var subDesc protoreflect.MessageDescriptor
322		if msgDesc != nil && !msgDesc.IsPlaceholder() {
323			if fieldDesc := msgDesc.Fields().ByNumber(num); fieldDesc != nil {
324				isPacked = fieldDesc.IsPacked()
325				kind = fieldDesc.Kind()
326				switch kind {
327				case protoreflect.MessageKind, protoreflect.GroupKind:
328					subDesc = fieldDesc.Message()
329					if subDesc == nil || subDesc.IsPlaceholder() {
330						kind = 0
331					}
332				}
333			}
334		}
335
336		switch typ {
337		case VarintType:
338			p.parseVarint(kind)
339		case Fixed32Type:
340			p.parseFixed32(kind)
341		case Fixed64Type:
342			p.parseFixed64(kind)
343		case BytesType:
344			p.parseBytes(isPacked, kind, subDesc)
345		case StartGroupType:
346			p.parseGroup(subDesc)
347		case EndGroupType:
348			// Handled above.
349		default:
350			p.out, p.in = append(p.out, Raw(p.in)), nil
351		}
352	}
353}
354
355func (p *parser) parseVarint(kind protoreflect.Kind) {
356	v, n := protowire.ConsumeVarint(p.in)
357	if n < 0 {
358		p.out, p.in = append(p.out, Raw(p.in)), nil
359		return
360	}
361	switch kind {
362	case protoreflect.BoolKind:
363		switch v {
364		case 0:
365			p.out, p.in = append(p.out, Bool(false)), p.in[n:]
366		case 1:
367			p.out, p.in = append(p.out, Bool(true)), p.in[n:]
368		default:
369			p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
370		}
371	case protoreflect.Int32Kind, protoreflect.Int64Kind:
372		p.out, p.in = append(p.out, Varint(v)), p.in[n:]
373	case protoreflect.Sint32Kind, protoreflect.Sint64Kind:
374		p.out, p.in = append(p.out, Svarint(protowire.DecodeZigZag(v))), p.in[n:]
375	default:
376		p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
377	}
378	if m := n - protowire.SizeVarint(v); m > 0 {
379		p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
380	}
381}
382
383func (p *parser) parseFixed32(kind protoreflect.Kind) {
384	v, n := protowire.ConsumeFixed32(p.in)
385	if n < 0 {
386		p.out, p.in = append(p.out, Raw(p.in)), nil
387		return
388	}
389	switch kind {
390	case protoreflect.FloatKind:
391		p.out, p.in = append(p.out, Float32(math.Float32frombits(v))), p.in[n:]
392	case protoreflect.Sfixed32Kind:
393		p.out, p.in = append(p.out, Int32(v)), p.in[n:]
394	default:
395		p.out, p.in = append(p.out, Uint32(v)), p.in[n:]
396	}
397}
398
399func (p *parser) parseFixed64(kind protoreflect.Kind) {
400	v, n := protowire.ConsumeFixed64(p.in)
401	if n < 0 {
402		p.out, p.in = append(p.out, Raw(p.in)), nil
403		return
404	}
405	switch kind {
406	case protoreflect.DoubleKind:
407		p.out, p.in = append(p.out, Float64(math.Float64frombits(v))), p.in[n:]
408	case protoreflect.Sfixed64Kind:
409		p.out, p.in = append(p.out, Int64(v)), p.in[n:]
410	default:
411		p.out, p.in = append(p.out, Uint64(v)), p.in[n:]
412	}
413}
414
415func (p *parser) parseBytes(isPacked bool, kind protoreflect.Kind, desc protoreflect.MessageDescriptor) {
416	v, n := protowire.ConsumeVarint(p.in)
417	if n < 0 {
418		p.out, p.in = append(p.out, Raw(p.in)), nil
419		return
420	}
421	p.out, p.in = append(p.out, Uvarint(v)), p.in[n:]
422	if m := n - protowire.SizeVarint(v); m > 0 {
423		p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
424	}
425	if v > uint64(len(p.in)) {
426		p.out, p.in = append(p.out, Raw(p.in)), nil
427		return
428	}
429	p.out = p.out[:len(p.out)-1] // subsequent tokens contain prefix-length
430
431	if isPacked {
432		p.parsePacked(int(v), kind)
433	} else {
434		switch kind {
435		case protoreflect.MessageKind:
436			p2 := parser{in: p.in[:v]}
437			p2.parseMessage(desc, false)
438			p.out, p.in = append(p.out, LengthPrefix(p2.out)), p.in[v:]
439		case protoreflect.StringKind:
440			p.out, p.in = append(p.out, String(p.in[:v])), p.in[v:]
441		default:
442			p.out, p.in = append(p.out, Bytes(p.in[:v])), p.in[v:]
443		}
444	}
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}
449
450func (p *parser) parsePacked(n int, kind protoreflect.Kind) {
451	p2 := parser{in: p.in[:n]}
452	for len(p2.in) > 0 {
453		switch kind {
454		case protoreflect.BoolKind, protoreflect.EnumKind,
455			protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Uint32Kind,
456			protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind:
457			p2.parseVarint(kind)
458		case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind:
459			p2.parseFixed32(kind)
460		case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind:
461			p2.parseFixed64(kind)
462		default:
463			panic(fmt.Sprintf("invalid packed kind: %v", kind))
464		}
465	}
466	p.out, p.in = append(p.out, LengthPrefix(p2.out)), p.in[n:]
467}
468
469func (p *parser) parseGroup(desc protoreflect.MessageDescriptor) {
470	p2 := parser{in: p.in}
471	p2.parseMessage(desc, true)
472	if len(p2.out) > 0 {
473		p.out = append(p.out, Message(p2.out))
474	}
475	p.in = p2.in
476
477	// Append the trailing end group.
478	v, n := protowire.ConsumeVarint(p.in)
479	if num, typ := protowire.DecodeTag(v); typ == EndGroupType {
480		p.out, p.in = append(p.out, Tag{num, typ}), p.in[n:]
481		if m := n - protowire.SizeVarint(v); m > 0 {
482			p.out[len(p.out)-1] = Denormalized{uint(m), p.out[len(p.out)-1]}
483		}
484	}
485}
486
487// Format implements a custom formatter to visualize the syntax tree.
488// Using "%#v" formats the Message in Go source code.
489func (m Message) Format(s fmt.State, r rune) {
490	switch r {
491	case 'x':
492		io.WriteString(s, fmt.Sprintf("%x", m.Marshal()))
493	case 'X':
494		io.WriteString(s, fmt.Sprintf("%X", m.Marshal()))
495	case 'v':
496		switch {
497		case s.Flag('#'):
498			io.WriteString(s, m.format(true, true))
499		case s.Flag('+'):
500			io.WriteString(s, m.format(false, true))
501		default:
502			io.WriteString(s, m.format(false, false))
503		}
504	default:
505		panic("invalid verb: " + string(r))
506	}
507}
508
509// format formats the message.
510// If source is enabled, this emits valid Go source.
511// If multi is enabled, the output may span multiple lines.
512func (m Message) format(source, multi bool) string {
513	var ss []string
514	var prefix, nextPrefix string
515	for _, v := range m {
516		// Ensure certain tokens have preceding or succeeding newlines.
517		prefix, nextPrefix = nextPrefix, " "
518		if multi {
519			switch v := v.(type) {
520			case Tag: // only has preceding newline
521				prefix = "\n"
522			case Denormalized: // only has preceding newline
523				if _, ok := v.Value.(Tag); ok {
524					prefix = "\n"
525				}
526			case Message, Raw: // has preceding and succeeding newlines
527				prefix, nextPrefix = "\n", "\n"
528			}
529		}
530
531		s := formatToken(v, source, multi)
532		ss = append(ss, prefix+s+",")
533	}
534
535	var s string
536	if len(ss) > 0 {
537		s = strings.TrimSpace(strings.Join(ss, ""))
538		if multi {
539			s = "\n\t" + strings.Join(strings.Split(s, "\n"), "\n\t") + "\n"
540		} else {
541			s = strings.TrimSuffix(s, ",")
542		}
543	}
544	s = fmt.Sprintf("%T{%s}", m, s)
545	if !source {
546		s = trimPackage(s)
547	}
548	return s
549}
550
551// formatToken formats a single token.
552func formatToken(t Token, source, multi bool) (s string) {
553	switch v := t.(type) {
554	case Message:
555		s = v.format(source, multi)
556	case LengthPrefix:
557		s = formatPacked(v, source, multi)
558		if s == "" {
559			ms := Message(v).format(source, multi)
560			s = fmt.Sprintf("%T(%s)", v, ms)
561		}
562	case Tag:
563		s = fmt.Sprintf("%T{%d, %s}", v, v.Number, formatType(v.Type, source))
564	case Bool, Varint, Svarint, Uvarint, Int32, Uint32, Float32, Int64, Uint64, Float64:
565		if source {
566			// Print floats in a way that preserves exact precision.
567			if f, _ := v.(Float32); math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) {
568				switch {
569				case f > 0:
570					s = fmt.Sprintf("%T(math.Inf(+1))", v)
571				case f < 0:
572					s = fmt.Sprintf("%T(math.Inf(-1))", v)
573				case math.Float32bits(float32(math.NaN())) == math.Float32bits(float32(f)):
574					s = fmt.Sprintf("%T(math.NaN())", v)
575				default:
576					s = fmt.Sprintf("%T(math.Float32frombits(0x%08x))", v, math.Float32bits(float32(f)))
577				}
578				break
579			}
580			if f, _ := v.(Float64); math.IsNaN(float64(f)) || math.IsInf(float64(f), 0) {
581				switch {
582				case f > 0:
583					s = fmt.Sprintf("%T(math.Inf(+1))", v)
584				case f < 0:
585					s = fmt.Sprintf("%T(math.Inf(-1))", v)
586				case math.Float64bits(float64(math.NaN())) == math.Float64bits(float64(f)):
587					s = fmt.Sprintf("%T(math.NaN())", v)
588				default:
589					s = fmt.Sprintf("%T(math.Float64frombits(0x%08x))", v, math.Float64bits(float64(f)))
590				}
591				break
592			}
593		}
594		s = fmt.Sprintf("%T(%v)", v, v)
595	case String, Bytes, Raw:
596		s = fmt.Sprintf("%s", v)
597		s = fmt.Sprintf("%T(%s)", v, formatString(s))
598	case Denormalized:
599		s = fmt.Sprintf("%T{+%d, %v}", v, v.Count, formatToken(v.Value, source, multi))
600	default:
601		panic(fmt.Sprintf("unknown type: %T", v))
602	}
603	if !source {
604		s = trimPackage(s)
605	}
606	return s
607}
608
609// formatPacked returns a non-empty string if LengthPrefix looks like a packed
610// repeated field of primitives.
611func formatPacked(v LengthPrefix, source, multi bool) string {
612	var ss []string
613	for _, v := range v {
614		switch v.(type) {
615		case Bool, Varint, Svarint, Uvarint, Int32, Uint32, Float32, Int64, Uint64, Float64, Denormalized, Raw:
616			if v, ok := v.(Denormalized); ok {
617				switch v.Value.(type) {
618				case Bool, Varint, Svarint, Uvarint:
619				default:
620					return ""
621				}
622			}
623			ss = append(ss, formatToken(v, source, multi))
624		default:
625			return ""
626		}
627	}
628	s := fmt.Sprintf("%T{%s}", v, strings.Join(ss, ", "))
629	if !source {
630		s = trimPackage(s)
631	}
632	return s
633}
634
635// formatType returns the name for Type.
636func formatType(t Type, source bool) (s string) {
637	switch t {
638	case VarintType:
639		s = pkg + ".VarintType"
640	case Fixed32Type:
641		s = pkg + ".Fixed32Type"
642	case Fixed64Type:
643		s = pkg + ".Fixed64Type"
644	case BytesType:
645		s = pkg + ".BytesType"
646	case StartGroupType:
647		s = pkg + ".StartGroupType"
648	case EndGroupType:
649		s = pkg + ".EndGroupType"
650	default:
651		s = fmt.Sprintf("Type(%d)", t)
652	}
653	if !source {
654		s = strings.TrimSuffix(trimPackage(s), "Type")
655	}
656	return s
657}
658
659// formatString returns a quoted string for s.
660func formatString(s string) string {
661	// Use quoted string if it the same length as a raw string literal.
662	// Otherwise, attempt to use the raw string form.
663	qs := strconv.Quote(s)
664	if len(qs) == 1+len(s)+1 {
665		return qs
666	}
667
668	// Disallow newlines to ensure output is a single line.
669	// Disallow non-printable runes for readability purposes.
670	rawInvalid := func(r rune) bool {
671		return r == '`' || r == '\n' || r == utf8.RuneError || !unicode.IsPrint(r)
672	}
673	if strings.IndexFunc(s, rawInvalid) < 0 {
674		return "`" + s + "`"
675	}
676	return qs
677}
678
679var pkg = path.Base(reflect.TypeOf(Tag{}).PkgPath())
680
681func trimPackage(s string) string {
682	return strings.TrimPrefix(strings.TrimPrefix(s, pkg), ".")
683}
684