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
37package proto
38
39// Functions for writing the text protocol buffer format.
40
41import (
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
57var (
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
71type writer interface {
72	io.Writer
73	WriteByte(byte) error
74}
75
76// textWriter is an io.Writer that tracks its indentation level.
77type 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
84func (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
98func (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
147func (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
159func (w *textWriter) indent() { w.ind++ }
160
161func (w *textWriter) unindent() {
162	if w.ind == 0 {
163		log.Print("proto: textWriter unindented too far")
164		return
165	}
166	w.ind--
167}
168
169func 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
179func 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
199func 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.
214func (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
260func (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// writeAny writes an arbitrary field.
480func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
481	v = reflect.Indirect(v)
482
483	if props != nil {
484		if len(props.CustomType) > 0 {
485			custom, ok := v.Interface().(Marshaler)
486			if ok {
487				data, err := custom.Marshal()
488				if err != nil {
489					return err
490				}
491				if err := writeString(w, string(data)); err != nil {
492					return err
493				}
494				return nil
495			}
496		} else if len(props.CastType) > 0 {
497			if _, ok := v.Interface().(interface {
498				String() string
499			}); ok {
500				switch v.Kind() {
501				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
502					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
503					_, err := fmt.Fprintf(w, "%d", v.Interface())
504					return err
505				}
506			}
507		} else if props.StdTime {
508			t, ok := v.Interface().(time.Time)
509			if !ok {
510				return fmt.Errorf("stdtime is not time.Time, but %T", v.Interface())
511			}
512			tproto, err := timestampProto(t)
513			if err != nil {
514				return err
515			}
516			propsCopy := *props // Make a copy so that this is goroutine-safe
517			propsCopy.StdTime = false
518			err = tm.writeAny(w, reflect.ValueOf(tproto), &propsCopy)
519			return err
520		} else if props.StdDuration {
521			d, ok := v.Interface().(time.Duration)
522			if !ok {
523				return fmt.Errorf("stdtime is not time.Duration, but %T", v.Interface())
524			}
525			dproto := durationProto(d)
526			propsCopy := *props // Make a copy so that this is goroutine-safe
527			propsCopy.StdDuration = false
528			err := tm.writeAny(w, reflect.ValueOf(dproto), &propsCopy)
529			return err
530		}
531	}
532
533	// Floats have special cases.
534	if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
535		x := v.Float()
536		var b []byte
537		switch {
538		case math.IsInf(x, 1):
539			b = posInf
540		case math.IsInf(x, -1):
541			b = negInf
542		case math.IsNaN(x):
543			b = nan
544		}
545		if b != nil {
546			_, err := w.Write(b)
547			return err
548		}
549		// Other values are handled below.
550	}
551
552	// We don't attempt to serialise every possible value type; only those
553	// that can occur in protocol buffers.
554	switch v.Kind() {
555	case reflect.Slice:
556		// Should only be a []byte; repeated fields are handled in writeStruct.
557		if err := writeString(w, string(v.Bytes())); err != nil {
558			return err
559		}
560	case reflect.String:
561		if err := writeString(w, v.String()); err != nil {
562			return err
563		}
564	case reflect.Struct:
565		// Required/optional group/message.
566		var bra, ket byte = '<', '>'
567		if props != nil && props.Wire == "group" {
568			bra, ket = '{', '}'
569		}
570		if err := w.WriteByte(bra); err != nil {
571			return err
572		}
573		if !w.compact {
574			if err := w.WriteByte('\n'); err != nil {
575				return err
576			}
577		}
578		w.indent()
579		if v.CanAddr() {
580			// Calling v.Interface on a struct causes the reflect package to
581			// copy the entire struct. This is racy with the new Marshaler
582			// since we atomically update the XXX_sizecache.
583			//
584			// Thus, we retrieve a pointer to the struct if possible to avoid
585			// a race since v.Interface on the pointer doesn't copy the struct.
586			//
587			// If v is not addressable, then we are not worried about a race
588			// since it implies that the binary Marshaler cannot possibly be
589			// mutating this value.
590			v = v.Addr()
591		}
592		if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
593			text, err := etm.MarshalText()
594			if err != nil {
595				return err
596			}
597			if _, err = w.Write(text); err != nil {
598				return err
599			}
600		} else {
601			if v.Kind() == reflect.Ptr {
602				v = v.Elem()
603			}
604			if err := tm.writeStruct(w, v); err != nil {
605				return err
606			}
607		}
608		w.unindent()
609		if err := w.WriteByte(ket); err != nil {
610			return err
611		}
612	default:
613		_, err := fmt.Fprint(w, v.Interface())
614		return err
615	}
616	return nil
617}
618
619// equivalent to C's isprint.
620func isprint(c byte) bool {
621	return c >= 0x20 && c < 0x7f
622}
623
624// writeString writes a string in the protocol buffer text format.
625// It is similar to strconv.Quote except we don't use Go escape sequences,
626// we treat the string as a byte sequence, and we use octal escapes.
627// These differences are to maintain interoperability with the other
628// languages' implementations of the text format.
629func writeString(w *textWriter, s string) error {
630	// use WriteByte here to get any needed indent
631	if err := w.WriteByte('"'); err != nil {
632		return err
633	}
634	// Loop over the bytes, not the runes.
635	for i := 0; i < len(s); i++ {
636		var err error
637		// Divergence from C++: we don't escape apostrophes.
638		// There's no need to escape them, and the C++ parser
639		// copes with a naked apostrophe.
640		switch c := s[i]; c {
641		case '\n':
642			_, err = w.w.Write(backslashN)
643		case '\r':
644			_, err = w.w.Write(backslashR)
645		case '\t':
646			_, err = w.w.Write(backslashT)
647		case '"':
648			_, err = w.w.Write(backslashDQ)
649		case '\\':
650			_, err = w.w.Write(backslashBS)
651		default:
652			if isprint(c) {
653				err = w.w.WriteByte(c)
654			} else {
655				_, err = fmt.Fprintf(w.w, "\\%03o", c)
656			}
657		}
658		if err != nil {
659			return err
660		}
661	}
662	return w.WriteByte('"')
663}
664
665func writeUnknownStruct(w *textWriter, data []byte) (err error) {
666	if !w.compact {
667		if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
668			return err
669		}
670	}
671	b := NewBuffer(data)
672	for b.index < len(b.buf) {
673		x, err := b.DecodeVarint()
674		if err != nil {
675			_, ferr := fmt.Fprintf(w, "/* %v */\n", err)
676			return ferr
677		}
678		wire, tag := x&7, x>>3
679		if wire == WireEndGroup {
680			w.unindent()
681			if _, werr := w.Write(endBraceNewline); werr != nil {
682				return werr
683			}
684			continue
685		}
686		if _, ferr := fmt.Fprint(w, tag); ferr != nil {
687			return ferr
688		}
689		if wire != WireStartGroup {
690			if err = w.WriteByte(':'); err != nil {
691				return err
692			}
693		}
694		if !w.compact || wire == WireStartGroup {
695			if err = w.WriteByte(' '); err != nil {
696				return err
697			}
698		}
699		switch wire {
700		case WireBytes:
701			buf, e := b.DecodeRawBytes(false)
702			if e == nil {
703				_, err = fmt.Fprintf(w, "%q", buf)
704			} else {
705				_, err = fmt.Fprintf(w, "/* %v */", e)
706			}
707		case WireFixed32:
708			x, err = b.DecodeFixed32()
709			err = writeUnknownInt(w, x, err)
710		case WireFixed64:
711			x, err = b.DecodeFixed64()
712			err = writeUnknownInt(w, x, err)
713		case WireStartGroup:
714			err = w.WriteByte('{')
715			w.indent()
716		case WireVarint:
717			x, err = b.DecodeVarint()
718			err = writeUnknownInt(w, x, err)
719		default:
720			_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
721		}
722		if err != nil {
723			return err
724		}
725		if err := w.WriteByte('\n'); err != nil {
726			return err
727		}
728	}
729	return nil
730}
731
732func writeUnknownInt(w *textWriter, x uint64, err error) error {
733	if err == nil {
734		_, err = fmt.Fprint(w, x)
735	} else {
736		_, err = fmt.Fprintf(w, "/* %v */", err)
737	}
738	return err
739}
740
741type int32Slice []int32
742
743func (s int32Slice) Len() int           { return len(s) }
744func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
745func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
746
747// writeExtensions writes all the extensions in pv.
748// pv is assumed to be a pointer to a protocol message struct that is extendable.
749func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
750	emap := extensionMaps[pv.Type().Elem()]
751	e := pv.Interface().(Message)
752
753	var m map[int32]Extension
754	var mu sync.Locker
755	if em, ok := e.(extensionsBytes); ok {
756		eb := em.GetExtensions()
757		var err error
758		m, err = BytesToExtensionsMap(*eb)
759		if err != nil {
760			return err
761		}
762		mu = notLocker{}
763	} else if _, ok := e.(extendableProto); ok {
764		ep, _ := extendable(e)
765		m, mu = ep.extensionsRead()
766		if m == nil {
767			return nil
768		}
769	}
770
771	// Order the extensions by ID.
772	// This isn't strictly necessary, but it will give us
773	// canonical output, which will also make testing easier.
774
775	mu.Lock()
776	ids := make([]int32, 0, len(m))
777	for id := range m {
778		ids = append(ids, id)
779	}
780	sort.Sort(int32Slice(ids))
781	mu.Unlock()
782
783	for _, extNum := range ids {
784		ext := m[extNum]
785		var desc *ExtensionDesc
786		if emap != nil {
787			desc = emap[extNum]
788		}
789		if desc == nil {
790			// Unknown extension.
791			if err := writeUnknownStruct(w, ext.enc); err != nil {
792				return err
793			}
794			continue
795		}
796
797		pb, err := GetExtension(e, desc)
798		if err != nil {
799			return fmt.Errorf("failed getting extension: %v", err)
800		}
801
802		// Repeated extensions will appear as a slice.
803		if !desc.repeated() {
804			if err := tm.writeExtension(w, desc.Name, pb); err != nil {
805				return err
806			}
807		} else {
808			v := reflect.ValueOf(pb)
809			for i := 0; i < v.Len(); i++ {
810				if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
811					return err
812				}
813			}
814		}
815	}
816	return nil
817}
818
819func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
820	if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
821		return err
822	}
823	if !w.compact {
824		if err := w.WriteByte(' '); err != nil {
825			return err
826		}
827	}
828	if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
829		return err
830	}
831	if err := w.WriteByte('\n'); err != nil {
832		return err
833	}
834	return nil
835}
836
837func (w *textWriter) writeIndent() {
838	if !w.complete {
839		return
840	}
841	remain := w.ind * 2
842	for remain > 0 {
843		n := remain
844		if n > len(spaces) {
845			n = len(spaces)
846		}
847		w.w.Write(spaces[:n])
848		remain -= n
849	}
850	w.complete = false
851}
852
853// TextMarshaler is a configurable text format marshaler.
854type TextMarshaler struct {
855	Compact   bool // use compact text format (one line).
856	ExpandAny bool // expand google.protobuf.Any messages of known types
857}
858
859// Marshal writes a given protocol buffer in text format.
860// The only errors returned are from w.
861func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
862	val := reflect.ValueOf(pb)
863	if pb == nil || val.IsNil() {
864		w.Write([]byte("<nil>"))
865		return nil
866	}
867	var bw *bufio.Writer
868	ww, ok := w.(writer)
869	if !ok {
870		bw = bufio.NewWriter(w)
871		ww = bw
872	}
873	aw := &textWriter{
874		w:        ww,
875		complete: true,
876		compact:  tm.Compact,
877	}
878
879	if etm, ok := pb.(encoding.TextMarshaler); ok {
880		text, err := etm.MarshalText()
881		if err != nil {
882			return err
883		}
884		if _, err = aw.Write(text); err != nil {
885			return err
886		}
887		if bw != nil {
888			return bw.Flush()
889		}
890		return nil
891	}
892	// Dereference the received pointer so we don't have outer < and >.
893	v := reflect.Indirect(val)
894	if err := tm.writeStruct(aw, v); err != nil {
895		return err
896	}
897	if bw != nil {
898		return bw.Flush()
899	}
900	return nil
901}
902
903// Text is the same as Marshal, but returns the string directly.
904func (tm *TextMarshaler) Text(pb Message) string {
905	var buf bytes.Buffer
906	tm.Marshal(&buf, pb)
907	return buf.String()
908}
909
910var (
911	defaultTextMarshaler = TextMarshaler{}
912	compactTextMarshaler = TextMarshaler{Compact: true}
913)
914
915// TODO: consider removing some of the Marshal functions below.
916
917// MarshalText writes a given protocol buffer in text format.
918// The only errors returned are from w.
919func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
920
921// MarshalTextString is the same as MarshalText, but returns the string directly.
922func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
923
924// CompactText writes a given protocol buffer in compact text format (one line).
925func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
926
927// CompactTextString is the same as CompactText, but returns the string directly.
928func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
929