// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors.  All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package proto

// Functions for writing the text protocol buffer format.

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
)

var (
	newline         = []byte("\n")
	spaces          = []byte("                                        ")
	endBraceNewline = []byte("}\n")
	backslashN      = []byte{'\\', 'n'}
	backslashR      = []byte{'\\', 'r'}
	backslashT      = []byte{'\\', 't'}
	backslashDQ     = []byte{'\\', '"'}
	backslashBS     = []byte{'\\', '\\'}
	posInf          = []byte("inf")
	negInf          = []byte("-inf")
	nan             = []byte("nan")
)

type writer interface {
	io.Writer
	WriteByte(byte) error
}

// textWriter is an io.Writer that tracks its indentation level.
type textWriter struct {
	ind      int
	complete bool // if the current position is a complete line
	compact  bool // whether to write out as a one-liner
	w        writer
}

func ( *textWriter) ( string) ( int,  error) {
	if !strings.Contains(, "\n") {
		if !.compact && .complete {
			.writeIndent()
		}
		.complete = false
		return io.WriteString(.w, )
	}
	// WriteString is typically called without newlines, so this
	// codepath and its copy are rare.  We copy to avoid
	// duplicating all of Write's logic here.
	return .Write([]byte())
}

func ( *textWriter) ( []byte) ( int,  error) {
	 := bytes.Count(, newline)
	if  == 0 {
		if !.compact && .complete {
			.writeIndent()
		}
		,  = .w.Write()
		.complete = false
		return , 
	}

	 := bytes.SplitN(, newline, +1)
	if .compact {
		for ,  := range  {
			if  > 0 {
				if  := .w.WriteByte(' ');  != nil {
					return , 
				}
				++
			}
			,  := .w.Write()
			 += 
			if  != nil {
				return , 
			}
		}
		return , nil
	}

	for ,  := range  {
		if .complete {
			.writeIndent()
		}
		,  := .w.Write()
		 += 
		if  != nil {
			return , 
		}
		if +1 < len() {
			if  := .w.WriteByte('\n');  != nil {
				return , 
			}
			++
		}
	}
	.complete = len([len()-1]) == 0
	return , nil
}

func ( *textWriter) ( byte) error {
	if .compact &&  == '\n' {
		 = ' '
	}
	if !.compact && .complete {
		.writeIndent()
	}
	 := .w.WriteByte()
	.complete =  == '\n'
	return 
}

func ( *textWriter) () { .ind++ }

func ( *textWriter) () {
	if .ind == 0 {
		log.Print("proto: textWriter unindented too far")
		return
	}
	.ind--
}

func writeName( *textWriter,  *Properties) error {
	if ,  := .WriteString(.OrigName);  != nil {
		return 
	}
	if .Wire != "group" {
		return .WriteByte(':')
	}
	return nil
}

func requiresQuotes( string) bool {
	// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
	for ,  := range  {
		switch {
		case  == '.' ||  == '/' ||  == '_':
			continue
		case '0' <=  &&  <= '9':
			continue
		case 'A' <=  &&  <= 'Z':
			continue
		case 'a' <=  &&  <= 'z':
			continue
		default:
			return true
		}
	}
	return false
}

// isAny reports whether sv is a google.protobuf.Any message
func isAny( reflect.Value) bool {
	type  interface {
		() string
	}
	,  := .Addr().Interface().()
	return  && .() == "Any"
}

// writeProto3Any writes an expanded google.protobuf.Any message.
//
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
// required messages are not linked in).
//
// It returns (true, error) when sv was written in expanded format or an error
// was encountered.
func ( *TextMarshaler) ( *textWriter,  reflect.Value) (bool, error) {
	 := .FieldByName("TypeUrl")
	 := .FieldByName("Value")
	if !.IsValid() || !.IsValid() {
		return true, errors.New("proto: invalid google.protobuf.Any message")
	}

	,  := .Interface().([]byte)
	if ! {
		return true, errors.New("proto: invalid google.protobuf.Any message")
	}

	 := strings.Split(.String(), "/")
	 := MessageType([len()-1])
	if  == nil {
		return false, nil
	}
	 := reflect.New(.Elem())
	if  := Unmarshal(, .Interface().(Message));  != nil {
		return false, nil
	}
	.Write([]byte("["))
	 := .String()
	if requiresQuotes() {
		writeString(, )
	} else {
		.Write([]byte())
	}
	if .compact {
		.Write([]byte("]:<"))
	} else {
		.Write([]byte("]: <\n"))
		.ind++
	}
	if  := .writeStruct(, .Elem());  != nil {
		return true, 
	}
	if .compact {
		.Write([]byte("> "))
	} else {
		.ind--
		.Write([]byte(">\n"))
	}
	return true, nil
}

func ( *TextMarshaler) ( *textWriter,  reflect.Value) error {
	if .ExpandAny && isAny() {
		if ,  := .writeProto3Any(, );  {
			return 
		}
	}
	 := .Type()
	 := GetProperties()
	for  := 0;  < .NumField(); ++ {
		 := .Field()
		 := .Prop[]
		 := .Field().Name

		if  == "XXX_NoUnkeyedLiteral" {
			continue
		}

		if strings.HasPrefix(, "XXX_") {
			// There are two XXX_ fields:
			//   XXX_unrecognized []byte
			//   XXX_extensions   map[int32]proto.Extension
			// The first is handled here;
			// the second is handled at the bottom of this function.
			if  == "XXX_unrecognized" && !.IsNil() {
				if  := writeUnknownStruct(, .Interface().([]byte));  != nil {
					return 
				}
			}
			continue
		}
		if .Kind() == reflect.Ptr && .IsNil() {
			// Field not filled in. This could be an optional field or
			// a required field that wasn't filled in. Either way, there
			// isn't anything we can show for it.
			continue
		}
		if .Kind() == reflect.Slice && .IsNil() {
			// Repeated field that is empty, or a bytes field that is unused.
			continue
		}

		if .Repeated && .Kind() == reflect.Slice {
			// Repeated field.
			for  := 0;  < .Len(); ++ {
				if  := writeName(, );  != nil {
					return 
				}
				if !.compact {
					if  := .WriteByte(' ');  != nil {
						return 
					}
				}
				 := .Index()
				if .Kind() == reflect.Ptr && .IsNil() {
					// A nil message in a repeated field is not valid,
					// but we can handle that more gracefully than panicking.
					if ,  := .Write([]byte("<nil>\n"));  != nil {
						return 
					}
					continue
				}
				if len(.Enum) > 0 {
					if  := .writeEnum(, , );  != nil {
						return 
					}
				} else if  := .writeAny(, , );  != nil {
					return 
				}
				if  := .WriteByte('\n');  != nil {
					return 
				}
			}
			continue
		}
		if .Kind() == reflect.Map {
			// Map fields are rendered as a repeated struct with key/value fields.
			 := .MapKeys()
			sort.Sort(mapKeys())
			for ,  := range  {
				 := .MapIndex()
				if  := writeName(, );  != nil {
					return 
				}
				if !.compact {
					if  := .WriteByte(' ');  != nil {
						return 
					}
				}
				// open struct
				if  := .WriteByte('<');  != nil {
					return 
				}
				if !.compact {
					if  := .WriteByte('\n');  != nil {
						return 
					}
				}
				.indent()
				// key
				if ,  := .WriteString("key:");  != nil {
					return 
				}
				if !.compact {
					if  := .WriteByte(' ');  != nil {
						return 
					}
				}
				if  := .writeAny(, , .MapKeyProp);  != nil {
					return 
				}
				if  := .WriteByte('\n');  != nil {
					return 
				}
				// nil values aren't legal, but we can avoid panicking because of them.
				if .Kind() != reflect.Ptr || !.IsNil() {
					// value
					if ,  := .WriteString("value:");  != nil {
						return 
					}
					if !.compact {
						if  := .WriteByte(' ');  != nil {
							return 
						}
					}
					if  := .writeAny(, , .MapValProp);  != nil {
						return 
					}
					if  := .WriteByte('\n');  != nil {
						return 
					}
				}
				// close struct
				.unindent()
				if  := .WriteByte('>');  != nil {
					return 
				}
				if  := .WriteByte('\n');  != nil {
					return 
				}
			}
			continue
		}
		if .proto3 && .Kind() == reflect.Slice && .Len() == 0 {
			// empty bytes field
			continue
		}
		if .proto3 && .Kind() != reflect.Ptr && .Kind() != reflect.Slice {
			// proto3 non-repeated scalar field; skip if zero value
			if isProto3Zero() {
				continue
			}
		}

		if .Kind() == reflect.Interface {
			// Check if it is a oneof.
			if .Field().Tag.Get("protobuf_oneof") != "" {
				// fv is nil, or holds a pointer to generated struct.
				// That generated struct has exactly one field,
				// which has a protobuf struct tag.
				if .IsNil() {
					continue
				}
				 := .Elem().Elem() // interface -> *T -> T
				 := .Type().Field(0).Tag.Get("protobuf")
				 = new(Properties) // Overwrite the outer props var, but not its pointee.
				.Parse()
				// Write the value in the oneof, not the oneof itself.
				 = .Field(0)

				// Special case to cope with malformed messages gracefully:
				// If the value in the oneof is a nil pointer, don't panic
				// in writeAny.
				if .Kind() == reflect.Ptr && .IsNil() {
					// Use errors.New so writeAny won't render quotes.
					 := errors.New("/* nil */")
					 = reflect.ValueOf(&).Elem()
				}
			}
		}

		if  := writeName(, );  != nil {
			return 
		}
		if !.compact {
			if  := .WriteByte(' ');  != nil {
				return 
			}
		}

		if len(.Enum) > 0 {
			if  := .writeEnum(, , );  != nil {
				return 
			}
		} else if  := .writeAny(, , );  != nil {
			return 
		}

		if  := .WriteByte('\n');  != nil {
			return 
		}
	}

	// Extensions (the XXX_extensions field).
	 := 
	if .CanAddr() {
		 = .Addr()
	} else {
		 = reflect.New(.Type())
		.Elem().Set()
	}
	if ,  := extendable(.Interface());  == nil {
		if  := .writeExtensions(, );  != nil {
			return 
		}
	}

	return nil
}

var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()

// writeAny writes an arbitrary field.
func ( *TextMarshaler) ( *textWriter,  reflect.Value,  *Properties) error {
	 = reflect.Indirect()

	if  != nil {
		if len(.CustomType) > 0 {
			,  := .Interface().(Marshaler)
			if  {
				,  := .Marshal()
				if  != nil {
					return 
				}
				if  := writeString(, string());  != nil {
					return 
				}
				return nil
			}
		} else if len(.CastType) > 0 {
			if ,  := .Interface().(interface {
				() string
			});  {
				switch .Kind() {
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
					reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
					,  := fmt.Fprintf(, "%d", .Interface())
					return 
				}
			}
		} else if .StdTime {
			,  := .Interface().(time.Time)
			if ! {
				return fmt.Errorf("stdtime is not time.Time, but %T", .Interface())
			}
			,  := timestampProto()
			if  != nil {
				return 
			}
			 := * // Make a copy so that this is goroutine-safe
			.StdTime = false
			 = .(, reflect.ValueOf(), &)
			return 
		} else if .StdDuration {
			,  := .Interface().(time.Duration)
			if ! {
				return fmt.Errorf("stdtime is not time.Duration, but %T", .Interface())
			}
			 := durationProto()
			 := * // Make a copy so that this is goroutine-safe
			.StdDuration = false
			 := .(, reflect.ValueOf(), &)
			return 
		}
	}

	// Floats have special cases.
	if .Kind() == reflect.Float32 || .Kind() == reflect.Float64 {
		 := .Float()
		var  []byte
		switch {
		case math.IsInf(, 1):
			 = posInf
		case math.IsInf(, -1):
			 = negInf
		case math.IsNaN():
			 = nan
		}
		if  != nil {
			,  := .Write()
			return 
		}
		// Other values are handled below.
	}

	// We don't attempt to serialise every possible value type; only those
	// that can occur in protocol buffers.
	switch .Kind() {
	case reflect.Slice:
		// Should only be a []byte; repeated fields are handled in writeStruct.
		if  := writeString(, string(.Bytes()));  != nil {
			return 
		}
	case reflect.String:
		if  := writeString(, .String());  != nil {
			return 
		}
	case reflect.Struct:
		// Required/optional group/message.
		var ,  byte = '<', '>'
		if  != nil && .Wire == "group" {
			,  = '{', '}'
		}
		if  := .WriteByte();  != nil {
			return 
		}
		if !.compact {
			if  := .WriteByte('\n');  != nil {
				return 
			}
		}
		.indent()
		if .CanAddr() {
			// Calling v.Interface on a struct causes the reflect package to
			// copy the entire struct. This is racy with the new Marshaler
			// since we atomically update the XXX_sizecache.
			//
			// Thus, we retrieve a pointer to the struct if possible to avoid
			// a race since v.Interface on the pointer doesn't copy the struct.
			//
			// If v is not addressable, then we are not worried about a race
			// since it implies that the binary Marshaler cannot possibly be
			// mutating this value.
			 = .Addr()
		}
		if .Type().Implements(textMarshalerType) {
			,  := .Interface().(encoding.TextMarshaler).MarshalText()
			if  != nil {
				return 
			}
			if _,  = .Write();  != nil {
				return 
			}
		} else {
			if .Kind() == reflect.Ptr {
				 = .Elem()
			}
			if  := .writeStruct(, );  != nil {
				return 
			}
		}
		.unindent()
		if  := .WriteByte();  != nil {
			return 
		}
	default:
		,  := fmt.Fprint(, .Interface())
		return 
	}
	return nil
}

// equivalent to C's isprint.
func isprint( byte) bool {
	return  >= 0x20 &&  < 0x7f
}

// writeString writes a string in the protocol buffer text format.
// It is similar to strconv.Quote except we don't use Go escape sequences,
// we treat the string as a byte sequence, and we use octal escapes.
// These differences are to maintain interoperability with the other
// languages' implementations of the text format.
func writeString( *textWriter,  string) error {
	// use WriteByte here to get any needed indent
	if  := .WriteByte('"');  != nil {
		return 
	}
	// Loop over the bytes, not the runes.
	for  := 0;  < len(); ++ {
		var  error
		// Divergence from C++: we don't escape apostrophes.
		// There's no need to escape them, and the C++ parser
		// copes with a naked apostrophe.
		switch  := [];  {
		case '\n':
			_,  = .w.Write(backslashN)
		case '\r':
			_,  = .w.Write(backslashR)
		case '\t':
			_,  = .w.Write(backslashT)
		case '"':
			_,  = .w.Write(backslashDQ)
		case '\\':
			_,  = .w.Write(backslashBS)
		default:
			if isprint() {
				 = .w.WriteByte()
			} else {
				_,  = fmt.Fprintf(.w, "\\%03o", )
			}
		}
		if  != nil {
			return 
		}
	}
	return .WriteByte('"')
}

func writeUnknownStruct( *textWriter,  []byte) ( error) {
	if !.compact {
		if ,  := fmt.Fprintf(, "/* %d unknown bytes */\n", len());  != nil {
			return 
		}
	}
	 := NewBuffer()
	for .index < len(.buf) {
		,  := .DecodeVarint()
		if  != nil {
			,  := fmt.Fprintf(, "/* %v */\n", )
			return 
		}
		,  := &7, >>3
		if  == WireEndGroup {
			.unindent()
			if ,  := .Write(endBraceNewline);  != nil {
				return 
			}
			continue
		}
		if ,  := fmt.Fprint(, );  != nil {
			return 
		}
		if  != WireStartGroup {
			if  = .WriteByte(':');  != nil {
				return 
			}
		}
		if !.compact ||  == WireStartGroup {
			if  = .WriteByte(' ');  != nil {
				return 
			}
		}
		switch  {
		case WireBytes:
			,  := .DecodeRawBytes(false)
			if  == nil {
				_,  = fmt.Fprintf(, "%q", )
			} else {
				_,  = fmt.Fprintf(, "/* %v */", )
			}
		case WireFixed32:
			,  = .DecodeFixed32()
			 = writeUnknownInt(, , )
		case WireFixed64:
			,  = .DecodeFixed64()
			 = writeUnknownInt(, , )
		case WireStartGroup:
			 = .WriteByte('{')
			.indent()
		case WireVarint:
			,  = .DecodeVarint()
			 = writeUnknownInt(, , )
		default:
			_,  = fmt.Fprintf(, "/* unknown wire type %d */", )
		}
		if  != nil {
			return 
		}
		if  := .WriteByte('\n');  != nil {
			return 
		}
	}
	return nil
}

func writeUnknownInt( *textWriter,  uint64,  error) error {
	if  == nil {
		_,  = fmt.Fprint(, )
	} else {
		_,  = fmt.Fprintf(, "/* %v */", )
	}
	return 
}

type int32Slice []int32

func ( int32Slice) () int           { return len() }
func ( int32Slice) (,  int) bool { return [] < [] }
func ( int32Slice) (,  int)      { [], [] = [], [] }

// writeExtensions writes all the extensions in pv.
// pv is assumed to be a pointer to a protocol message struct that is extendable.
func ( *TextMarshaler) ( *textWriter,  reflect.Value) error {
	 := extensionMaps[.Type().Elem()]
	 := .Interface().(Message)

	var  map[int32]Extension
	var  sync.Locker
	if ,  := .(extensionsBytes);  {
		 := .GetExtensions()
		var  error
		,  = BytesToExtensionsMap(*)
		if  != nil {
			return 
		}
		 = notLocker{}
	} else if ,  := .(extendableProto);  {
		,  := extendable()
		,  = .extensionsRead()
		if  == nil {
			return nil
		}
	}

	// Order the extensions by ID.
	// This isn't strictly necessary, but it will give us
	// canonical output, which will also make testing easier.

	.Lock()
	 := make([]int32, 0, len())
	for  := range  {
		 = append(, )
	}
	sort.Sort(int32Slice())
	.Unlock()

	for ,  := range  {
		 := []
		var  *ExtensionDesc
		if  != nil {
			 = []
		}
		if  == nil {
			// Unknown extension.
			if  := writeUnknownStruct(, .enc);  != nil {
				return 
			}
			continue
		}

		,  := GetExtension(, )
		if  != nil {
			return fmt.Errorf("failed getting extension: %v", )
		}

		// Repeated extensions will appear as a slice.
		if !.repeated() {
			if  := .writeExtension(, .Name, );  != nil {
				return 
			}
		} else {
			 := reflect.ValueOf()
			for  := 0;  < .Len(); ++ {
				if  := .writeExtension(, .Name, .Index().Interface());  != nil {
					return 
				}
			}
		}
	}
	return nil
}

func ( *TextMarshaler) ( *textWriter,  string,  interface{}) error {
	if ,  := fmt.Fprintf(, "[%s]:", );  != nil {
		return 
	}
	if !.compact {
		if  := .WriteByte(' ');  != nil {
			return 
		}
	}
	if  := .writeAny(, reflect.ValueOf(), nil);  != nil {
		return 
	}
	if  := .WriteByte('\n');  != nil {
		return 
	}
	return nil
}

func ( *textWriter) () {
	if !.complete {
		return
	}
	 := .ind * 2
	for  > 0 {
		 := 
		if  > len(spaces) {
			 = len(spaces)
		}
		.w.Write(spaces[:])
		 -= 
	}
	.complete = false
}

// TextMarshaler is a configurable text format marshaler.
type TextMarshaler struct {
	Compact   bool // use compact text format (one line).
	ExpandAny bool // expand google.protobuf.Any messages of known types
}

// Marshal writes a given protocol buffer in text format.
// The only errors returned are from w.
func ( *TextMarshaler) ( io.Writer,  Message) error {
	 := reflect.ValueOf()
	if  == nil || .IsNil() {
		.Write([]byte("<nil>"))
		return nil
	}
	var  *bufio.Writer
	,  := .(writer)
	if ! {
		 = bufio.NewWriter()
		 = 
	}
	 := &textWriter{
		w:        ,
		complete: true,
		compact:  .Compact,
	}

	if ,  := .(encoding.TextMarshaler);  {
		,  := .MarshalText()
		if  != nil {
			return 
		}
		if _,  = .Write();  != nil {
			return 
		}
		if  != nil {
			return .Flush()
		}
		return nil
	}
	// Dereference the received pointer so we don't have outer < and >.
	 := reflect.Indirect()
	if  := .writeStruct(, );  != nil {
		return 
	}
	if  != nil {
		return .Flush()
	}
	return nil
}

// Text is the same as Marshal, but returns the string directly.
func ( *TextMarshaler) ( Message) string {
	var  bytes.Buffer
	.Marshal(&, )
	return .String()
}

var (
	defaultTextMarshaler = TextMarshaler{}
	compactTextMarshaler = TextMarshaler{Compact: true}
)

// TODO: consider removing some of the Marshal functions below.

// MarshalText writes a given protocol buffer in text format.
// The only errors returned are from w.
func ( io.Writer,  Message) error { return defaultTextMarshaler.Marshal(, ) }

// MarshalTextString is the same as MarshalText, but returns the string directly.
func ( Message) string { return defaultTextMarshaler.Text() }

// CompactText writes a given protocol buffer in compact text format (one line).
func ( io.Writer,  Message) error { return compactTextMarshaler.Marshal(, ) }

// CompactTextString is the same as CompactText, but returns the string directly.
func ( Message) string { return compactTextMarshaler.Text() }