OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / golang / protobuf / proto / text.go
1 // Go support for Protocol Buffers - Google's data interchange format
2 //
3 // Copyright 2010 The Go Authors.  All rights reserved.
4 // https://github.com/golang/protobuf
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 package proto
33
34 // Functions for writing the text protocol buffer format.
35
36 import (
37         "bufio"
38         "bytes"
39         "encoding"
40         "errors"
41         "fmt"
42         "io"
43         "log"
44         "math"
45         "reflect"
46         "sort"
47         "strings"
48 )
49
50 var (
51         newline         = []byte("\n")
52         spaces          = []byte("                                        ")
53         gtNewline       = []byte(">\n")
54         endBraceNewline = []byte("}\n")
55         backslashN      = []byte{'\\', 'n'}
56         backslashR      = []byte{'\\', 'r'}
57         backslashT      = []byte{'\\', 't'}
58         backslashDQ     = []byte{'\\', '"'}
59         backslashBS     = []byte{'\\', '\\'}
60         posInf          = []byte("inf")
61         negInf          = []byte("-inf")
62         nan             = []byte("nan")
63 )
64
65 type writer interface {
66         io.Writer
67         WriteByte(byte) error
68 }
69
70 // textWriter is an io.Writer that tracks its indentation level.
71 type textWriter struct {
72         ind      int
73         complete bool // if the current position is a complete line
74         compact  bool // whether to write out as a one-liner
75         w        writer
76 }
77
78 func (w *textWriter) WriteString(s string) (n int, err error) {
79         if !strings.Contains(s, "\n") {
80                 if !w.compact && w.complete {
81                         w.writeIndent()
82                 }
83                 w.complete = false
84                 return io.WriteString(w.w, s)
85         }
86         // WriteString is typically called without newlines, so this
87         // codepath and its copy are rare.  We copy to avoid
88         // duplicating all of Write's logic here.
89         return w.Write([]byte(s))
90 }
91
92 func (w *textWriter) Write(p []byte) (n int, err error) {
93         newlines := bytes.Count(p, newline)
94         if newlines == 0 {
95                 if !w.compact && w.complete {
96                         w.writeIndent()
97                 }
98                 n, err = w.w.Write(p)
99                 w.complete = false
100                 return n, err
101         }
102
103         frags := bytes.SplitN(p, newline, newlines+1)
104         if w.compact {
105                 for i, frag := range frags {
106                         if i > 0 {
107                                 if err := w.w.WriteByte(' '); err != nil {
108                                         return n, err
109                                 }
110                                 n++
111                         }
112                         nn, err := w.w.Write(frag)
113                         n += nn
114                         if err != nil {
115                                 return n, err
116                         }
117                 }
118                 return n, nil
119         }
120
121         for i, frag := range frags {
122                 if w.complete {
123                         w.writeIndent()
124                 }
125                 nn, err := w.w.Write(frag)
126                 n += nn
127                 if err != nil {
128                         return n, err
129                 }
130                 if i+1 < len(frags) {
131                         if err := w.w.WriteByte('\n'); err != nil {
132                                 return n, err
133                         }
134                         n++
135                 }
136         }
137         w.complete = len(frags[len(frags)-1]) == 0
138         return n, nil
139 }
140
141 func (w *textWriter) WriteByte(c byte) error {
142         if w.compact && c == '\n' {
143                 c = ' '
144         }
145         if !w.compact && w.complete {
146                 w.writeIndent()
147         }
148         err := w.w.WriteByte(c)
149         w.complete = c == '\n'
150         return err
151 }
152
153 func (w *textWriter) indent() { w.ind++ }
154
155 func (w *textWriter) unindent() {
156         if w.ind == 0 {
157                 log.Print("proto: textWriter unindented too far")
158                 return
159         }
160         w.ind--
161 }
162
163 func writeName(w *textWriter, props *Properties) error {
164         if _, err := w.WriteString(props.OrigName); err != nil {
165                 return err
166         }
167         if props.Wire != "group" {
168                 return w.WriteByte(':')
169         }
170         return nil
171 }
172
173 // raw is the interface satisfied by RawMessage.
174 type raw interface {
175         Bytes() []byte
176 }
177
178 func requiresQuotes(u string) bool {
179         // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
180         for _, ch := range u {
181                 switch {
182                 case ch == '.' || ch == '/' || ch == '_':
183                         continue
184                 case '0' <= ch && ch <= '9':
185                         continue
186                 case 'A' <= ch && ch <= 'Z':
187                         continue
188                 case 'a' <= ch && ch <= 'z':
189                         continue
190                 default:
191                         return true
192                 }
193         }
194         return false
195 }
196
197 // isAny reports whether sv is a google.protobuf.Any message
198 func isAny(sv reflect.Value) bool {
199         type wkt interface {
200                 XXX_WellKnownType() string
201         }
202         t, ok := sv.Addr().Interface().(wkt)
203         return ok && t.XXX_WellKnownType() == "Any"
204 }
205
206 // writeProto3Any writes an expanded google.protobuf.Any message.
207 //
208 // It returns (false, nil) if sv value can't be unmarshaled (e.g. because
209 // required messages are not linked in).
210 //
211 // It returns (true, error) when sv was written in expanded format or an error
212 // was encountered.
213 func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
214         turl := sv.FieldByName("TypeUrl")
215         val := sv.FieldByName("Value")
216         if !turl.IsValid() || !val.IsValid() {
217                 return true, errors.New("proto: invalid google.protobuf.Any message")
218         }
219
220         b, ok := val.Interface().([]byte)
221         if !ok {
222                 return true, errors.New("proto: invalid google.protobuf.Any message")
223         }
224
225         parts := strings.Split(turl.String(), "/")
226         mt := MessageType(parts[len(parts)-1])
227         if mt == nil {
228                 return false, nil
229         }
230         m := reflect.New(mt.Elem())
231         if err := Unmarshal(b, m.Interface().(Message)); err != nil {
232                 return false, nil
233         }
234         w.Write([]byte("["))
235         u := turl.String()
236         if requiresQuotes(u) {
237                 writeString(w, u)
238         } else {
239                 w.Write([]byte(u))
240         }
241         if w.compact {
242                 w.Write([]byte("]:<"))
243         } else {
244                 w.Write([]byte("]: <\n"))
245                 w.ind++
246         }
247         if err := tm.writeStruct(w, m.Elem()); err != nil {
248                 return true, err
249         }
250         if w.compact {
251                 w.Write([]byte("> "))
252         } else {
253                 w.ind--
254                 w.Write([]byte(">\n"))
255         }
256         return true, nil
257 }
258
259 func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
260         if tm.ExpandAny && isAny(sv) {
261                 if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
262                         return err
263                 }
264         }
265         st := sv.Type()
266         sprops := GetProperties(st)
267         for i := 0; i < sv.NumField(); i++ {
268                 fv := sv.Field(i)
269                 props := sprops.Prop[i]
270                 name := st.Field(i).Name
271
272                 if strings.HasPrefix(name, "XXX_") {
273                         // There are two XXX_ fields:
274                         //   XXX_unrecognized []byte
275                         //   XXX_extensions   map[int32]proto.Extension
276                         // The first is handled here;
277                         // the second is handled at the bottom of this function.
278                         if name == "XXX_unrecognized" && !fv.IsNil() {
279                                 if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
280                                         return err
281                                 }
282                         }
283                         continue
284                 }
285                 if fv.Kind() == reflect.Ptr && fv.IsNil() {
286                         // Field not filled in. This could be an optional field or
287                         // a required field that wasn't filled in. Either way, there
288                         // isn't anything we can show for it.
289                         continue
290                 }
291                 if fv.Kind() == reflect.Slice && fv.IsNil() {
292                         // Repeated field that is empty, or a bytes field that is unused.
293                         continue
294                 }
295
296                 if props.Repeated && fv.Kind() == reflect.Slice {
297                         // Repeated field.
298                         for j := 0; j < fv.Len(); j++ {
299                                 if err := writeName(w, props); err != nil {
300                                         return err
301                                 }
302                                 if !w.compact {
303                                         if err := w.WriteByte(' '); err != nil {
304                                                 return err
305                                         }
306                                 }
307                                 v := fv.Index(j)
308                                 if v.Kind() == reflect.Ptr && v.IsNil() {
309                                         // A nil message in a repeated field is not valid,
310                                         // but we can handle that more gracefully than panicking.
311                                         if _, err := w.Write([]byte("<nil>\n")); err != nil {
312                                                 return err
313                                         }
314                                         continue
315                                 }
316                                 if err := tm.writeAny(w, v, props); err != nil {
317                                         return err
318                                 }
319                                 if err := w.WriteByte('\n'); err != nil {
320                                         return err
321                                 }
322                         }
323                         continue
324                 }
325                 if fv.Kind() == reflect.Map {
326                         // Map fields are rendered as a repeated struct with key/value fields.
327                         keys := fv.MapKeys()
328                         sort.Sort(mapKeys(keys))
329                         for _, key := range keys {
330                                 val := fv.MapIndex(key)
331                                 if err := writeName(w, props); err != nil {
332                                         return err
333                                 }
334                                 if !w.compact {
335                                         if err := w.WriteByte(' '); err != nil {
336                                                 return err
337                                         }
338                                 }
339                                 // open struct
340                                 if err := w.WriteByte('<'); err != nil {
341                                         return err
342                                 }
343                                 if !w.compact {
344                                         if err := w.WriteByte('\n'); err != nil {
345                                                 return err
346                                         }
347                                 }
348                                 w.indent()
349                                 // key
350                                 if _, err := w.WriteString("key:"); err != nil {
351                                         return err
352                                 }
353                                 if !w.compact {
354                                         if err := w.WriteByte(' '); err != nil {
355                                                 return err
356                                         }
357                                 }
358                                 if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
359                                         return err
360                                 }
361                                 if err := w.WriteByte('\n'); err != nil {
362                                         return err
363                                 }
364                                 // nil values aren't legal, but we can avoid panicking because of them.
365                                 if val.Kind() != reflect.Ptr || !val.IsNil() {
366                                         // value
367                                         if _, err := w.WriteString("value:"); err != nil {
368                                                 return err
369                                         }
370                                         if !w.compact {
371                                                 if err := w.WriteByte(' '); err != nil {
372                                                         return err
373                                                 }
374                                         }
375                                         if err := tm.writeAny(w, val, props.mvalprop); err != nil {
376                                                 return err
377                                         }
378                                         if err := w.WriteByte('\n'); err != nil {
379                                                 return err
380                                         }
381                                 }
382                                 // close struct
383                                 w.unindent()
384                                 if err := w.WriteByte('>'); err != nil {
385                                         return err
386                                 }
387                                 if err := w.WriteByte('\n'); err != nil {
388                                         return err
389                                 }
390                         }
391                         continue
392                 }
393                 if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
394                         // empty bytes field
395                         continue
396                 }
397                 if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
398                         // proto3 non-repeated scalar field; skip if zero value
399                         if isProto3Zero(fv) {
400                                 continue
401                         }
402                 }
403
404                 if fv.Kind() == reflect.Interface {
405                         // Check if it is a oneof.
406                         if st.Field(i).Tag.Get("protobuf_oneof") != "" {
407                                 // fv is nil, or holds a pointer to generated struct.
408                                 // That generated struct has exactly one field,
409                                 // which has a protobuf struct tag.
410                                 if fv.IsNil() {
411                                         continue
412                                 }
413                                 inner := fv.Elem().Elem() // interface -> *T -> T
414                                 tag := inner.Type().Field(0).Tag.Get("protobuf")
415                                 props = new(Properties) // Overwrite the outer props var, but not its pointee.
416                                 props.Parse(tag)
417                                 // Write the value in the oneof, not the oneof itself.
418                                 fv = inner.Field(0)
419
420                                 // Special case to cope with malformed messages gracefully:
421                                 // If the value in the oneof is a nil pointer, don't panic
422                                 // in writeAny.
423                                 if fv.Kind() == reflect.Ptr && fv.IsNil() {
424                                         // Use errors.New so writeAny won't render quotes.
425                                         msg := errors.New("/* nil */")
426                                         fv = reflect.ValueOf(&msg).Elem()
427                                 }
428                         }
429                 }
430
431                 if err := writeName(w, props); err != nil {
432                         return err
433                 }
434                 if !w.compact {
435                         if err := w.WriteByte(' '); err != nil {
436                                 return err
437                         }
438                 }
439                 if b, ok := fv.Interface().(raw); ok {
440                         if err := writeRaw(w, b.Bytes()); err != nil {
441                                 return err
442                         }
443                         continue
444                 }
445
446                 // Enums have a String method, so writeAny will work fine.
447                 if err := tm.writeAny(w, fv, props); err != nil {
448                         return err
449                 }
450
451                 if err := w.WriteByte('\n'); err != nil {
452                         return err
453                 }
454         }
455
456         // Extensions (the XXX_extensions field).
457         pv := sv.Addr()
458         if _, ok := extendable(pv.Interface()); ok {
459                 if err := tm.writeExtensions(w, pv); err != nil {
460                         return err
461                 }
462         }
463
464         return nil
465 }
466
467 // writeRaw writes an uninterpreted raw message.
468 func writeRaw(w *textWriter, b []byte) error {
469         if err := w.WriteByte('<'); err != nil {
470                 return err
471         }
472         if !w.compact {
473                 if err := w.WriteByte('\n'); err != nil {
474                         return err
475                 }
476         }
477         w.indent()
478         if err := writeUnknownStruct(w, b); err != nil {
479                 return err
480         }
481         w.unindent()
482         if err := w.WriteByte('>'); err != nil {
483                 return err
484         }
485         return nil
486 }
487
488 // writeAny writes an arbitrary field.
489 func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
490         v = reflect.Indirect(v)
491
492         // Floats have special cases.
493         if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
494                 x := v.Float()
495                 var b []byte
496                 switch {
497                 case math.IsInf(x, 1):
498                         b = posInf
499                 case math.IsInf(x, -1):
500                         b = negInf
501                 case math.IsNaN(x):
502                         b = nan
503                 }
504                 if b != nil {
505                         _, err := w.Write(b)
506                         return err
507                 }
508                 // Other values are handled below.
509         }
510
511         // We don't attempt to serialise every possible value type; only those
512         // that can occur in protocol buffers.
513         switch v.Kind() {
514         case reflect.Slice:
515                 // Should only be a []byte; repeated fields are handled in writeStruct.
516                 if err := writeString(w, string(v.Bytes())); err != nil {
517                         return err
518                 }
519         case reflect.String:
520                 if err := writeString(w, v.String()); err != nil {
521                         return err
522                 }
523         case reflect.Struct:
524                 // Required/optional group/message.
525                 var bra, ket byte = '<', '>'
526                 if props != nil && props.Wire == "group" {
527                         bra, ket = '{', '}'
528                 }
529                 if err := w.WriteByte(bra); err != nil {
530                         return err
531                 }
532                 if !w.compact {
533                         if err := w.WriteByte('\n'); err != nil {
534                                 return err
535                         }
536                 }
537                 w.indent()
538                 if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
539                         text, err := etm.MarshalText()
540                         if err != nil {
541                                 return err
542                         }
543                         if _, err = w.Write(text); err != nil {
544                                 return err
545                         }
546                 } else if err := tm.writeStruct(w, v); err != nil {
547                         return err
548                 }
549                 w.unindent()
550                 if err := w.WriteByte(ket); err != nil {
551                         return err
552                 }
553         default:
554                 _, err := fmt.Fprint(w, v.Interface())
555                 return err
556         }
557         return nil
558 }
559
560 // equivalent to C's isprint.
561 func isprint(c byte) bool {
562         return c >= 0x20 && c < 0x7f
563 }
564
565 // writeString writes a string in the protocol buffer text format.
566 // It is similar to strconv.Quote except we don't use Go escape sequences,
567 // we treat the string as a byte sequence, and we use octal escapes.
568 // These differences are to maintain interoperability with the other
569 // languages' implementations of the text format.
570 func writeString(w *textWriter, s string) error {
571         // use WriteByte here to get any needed indent
572         if err := w.WriteByte('"'); err != nil {
573                 return err
574         }
575         // Loop over the bytes, not the runes.
576         for i := 0; i < len(s); i++ {
577                 var err error
578                 // Divergence from C++: we don't escape apostrophes.
579                 // There's no need to escape them, and the C++ parser
580                 // copes with a naked apostrophe.
581                 switch c := s[i]; c {
582                 case '\n':
583                         _, err = w.w.Write(backslashN)
584                 case '\r':
585                         _, err = w.w.Write(backslashR)
586                 case '\t':
587                         _, err = w.w.Write(backslashT)
588                 case '"':
589                         _, err = w.w.Write(backslashDQ)
590                 case '\\':
591                         _, err = w.w.Write(backslashBS)
592                 default:
593                         if isprint(c) {
594                                 err = w.w.WriteByte(c)
595                         } else {
596                                 _, err = fmt.Fprintf(w.w, "\\%03o", c)
597                         }
598                 }
599                 if err != nil {
600                         return err
601                 }
602         }
603         return w.WriteByte('"')
604 }
605
606 func writeUnknownStruct(w *textWriter, data []byte) (err error) {
607         if !w.compact {
608                 if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
609                         return err
610                 }
611         }
612         b := NewBuffer(data)
613         for b.index < len(b.buf) {
614                 x, err := b.DecodeVarint()
615                 if err != nil {
616                         _, err := fmt.Fprintf(w, "/* %v */\n", err)
617                         return err
618                 }
619                 wire, tag := x&7, x>>3
620                 if wire == WireEndGroup {
621                         w.unindent()
622                         if _, err := w.Write(endBraceNewline); err != nil {
623                                 return err
624                         }
625                         continue
626                 }
627                 if _, err := fmt.Fprint(w, tag); err != nil {
628                         return err
629                 }
630                 if wire != WireStartGroup {
631                         if err := w.WriteByte(':'); err != nil {
632                                 return err
633                         }
634                 }
635                 if !w.compact || wire == WireStartGroup {
636                         if err := w.WriteByte(' '); err != nil {
637                                 return err
638                         }
639                 }
640                 switch wire {
641                 case WireBytes:
642                         buf, e := b.DecodeRawBytes(false)
643                         if e == nil {
644                                 _, err = fmt.Fprintf(w, "%q", buf)
645                         } else {
646                                 _, err = fmt.Fprintf(w, "/* %v */", e)
647                         }
648                 case WireFixed32:
649                         x, err = b.DecodeFixed32()
650                         err = writeUnknownInt(w, x, err)
651                 case WireFixed64:
652                         x, err = b.DecodeFixed64()
653                         err = writeUnknownInt(w, x, err)
654                 case WireStartGroup:
655                         err = w.WriteByte('{')
656                         w.indent()
657                 case WireVarint:
658                         x, err = b.DecodeVarint()
659                         err = writeUnknownInt(w, x, err)
660                 default:
661                         _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
662                 }
663                 if err != nil {
664                         return err
665                 }
666                 if err = w.WriteByte('\n'); err != nil {
667                         return err
668                 }
669         }
670         return nil
671 }
672
673 func writeUnknownInt(w *textWriter, x uint64, err error) error {
674         if err == nil {
675                 _, err = fmt.Fprint(w, x)
676         } else {
677                 _, err = fmt.Fprintf(w, "/* %v */", err)
678         }
679         return err
680 }
681
682 type int32Slice []int32
683
684 func (s int32Slice) Len() int           { return len(s) }
685 func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
686 func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
687
688 // writeExtensions writes all the extensions in pv.
689 // pv is assumed to be a pointer to a protocol message struct that is extendable.
690 func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
691         emap := extensionMaps[pv.Type().Elem()]
692         ep, _ := extendable(pv.Interface())
693
694         // Order the extensions by ID.
695         // This isn't strictly necessary, but it will give us
696         // canonical output, which will also make testing easier.
697         m, mu := ep.extensionsRead()
698         if m == nil {
699                 return nil
700         }
701         mu.Lock()
702         ids := make([]int32, 0, len(m))
703         for id := range m {
704                 ids = append(ids, id)
705         }
706         sort.Sort(int32Slice(ids))
707         mu.Unlock()
708
709         for _, extNum := range ids {
710                 ext := m[extNum]
711                 var desc *ExtensionDesc
712                 if emap != nil {
713                         desc = emap[extNum]
714                 }
715                 if desc == nil {
716                         // Unknown extension.
717                         if err := writeUnknownStruct(w, ext.enc); err != nil {
718                                 return err
719                         }
720                         continue
721                 }
722
723                 pb, err := GetExtension(ep, desc)
724                 if err != nil {
725                         return fmt.Errorf("failed getting extension: %v", err)
726                 }
727
728                 // Repeated extensions will appear as a slice.
729                 if !desc.repeated() {
730                         if err := tm.writeExtension(w, desc.Name, pb); err != nil {
731                                 return err
732                         }
733                 } else {
734                         v := reflect.ValueOf(pb)
735                         for i := 0; i < v.Len(); i++ {
736                                 if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
737                                         return err
738                                 }
739                         }
740                 }
741         }
742         return nil
743 }
744
745 func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
746         if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
747                 return err
748         }
749         if !w.compact {
750                 if err := w.WriteByte(' '); err != nil {
751                         return err
752                 }
753         }
754         if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
755                 return err
756         }
757         if err := w.WriteByte('\n'); err != nil {
758                 return err
759         }
760         return nil
761 }
762
763 func (w *textWriter) writeIndent() {
764         if !w.complete {
765                 return
766         }
767         remain := w.ind * 2
768         for remain > 0 {
769                 n := remain
770                 if n > len(spaces) {
771                         n = len(spaces)
772                 }
773                 w.w.Write(spaces[:n])
774                 remain -= n
775         }
776         w.complete = false
777 }
778
779 // TextMarshaler is a configurable text format marshaler.
780 type TextMarshaler struct {
781         Compact   bool // use compact text format (one line).
782         ExpandAny bool // expand google.protobuf.Any messages of known types
783 }
784
785 // Marshal writes a given protocol buffer in text format.
786 // The only errors returned are from w.
787 func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
788         val := reflect.ValueOf(pb)
789         if pb == nil || val.IsNil() {
790                 w.Write([]byte("<nil>"))
791                 return nil
792         }
793         var bw *bufio.Writer
794         ww, ok := w.(writer)
795         if !ok {
796                 bw = bufio.NewWriter(w)
797                 ww = bw
798         }
799         aw := &textWriter{
800                 w:        ww,
801                 complete: true,
802                 compact:  tm.Compact,
803         }
804
805         if etm, ok := pb.(encoding.TextMarshaler); ok {
806                 text, err := etm.MarshalText()
807                 if err != nil {
808                         return err
809                 }
810                 if _, err = aw.Write(text); err != nil {
811                         return err
812                 }
813                 if bw != nil {
814                         return bw.Flush()
815                 }
816                 return nil
817         }
818         // Dereference the received pointer so we don't have outer < and >.
819         v := reflect.Indirect(val)
820         if err := tm.writeStruct(aw, v); err != nil {
821                 return err
822         }
823         if bw != nil {
824                 return bw.Flush()
825         }
826         return nil
827 }
828
829 // Text is the same as Marshal, but returns the string directly.
830 func (tm *TextMarshaler) Text(pb Message) string {
831         var buf bytes.Buffer
832         tm.Marshal(&buf, pb)
833         return buf.String()
834 }
835
836 var (
837         defaultTextMarshaler = TextMarshaler{}
838         compactTextMarshaler = TextMarshaler{Compact: true}
839 )
840
841 // TODO: consider removing some of the Marshal functions below.
842
843 // MarshalText writes a given protocol buffer in text format.
844 // The only errors returned are from w.
845 func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
846
847 // MarshalTextString is the same as MarshalText, but returns the string directly.
848 func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
849
850 // CompactText writes a given protocol buffer in compact text format (one line).
851 func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
852
853 // CompactTextString is the same as CompactText, but returns the string directly.
854 func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }