...

Source file src/github.com/gogo/protobuf/proto/text.go

Documentation: github.com/gogo/protobuf/proto

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

View as plain text