// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2011 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.

// Protocol buffer deep copy and merge.
// TODO: RawMessage.

package proto

import (
	
	
	
	
)

// Clone returns a deep copy of a protocol buffer.
func ( Message) Message {
	 := reflect.ValueOf()
	if .IsNil() {
		return 
	}
	 := reflect.New(.Type().Elem())
	 := .Interface().(Message)
	Merge(, )
	return 
}

// Merger is the interface representing objects that can merge messages of the same type.
type Merger interface {
	// Merge merges src into this message.
	// Required and optional fields that are set in src will be set to that value in dst.
	// Elements of repeated fields will be appended.
	//
	// Merge may panic if called with a different argument type than the receiver.
	Merge(src Message)
}

// generatedMerger is the custom merge method that generated protos will have.
// We must add this method since a generate Merge method will conflict with
// many existing protos that have a Merge data field already defined.
type generatedMerger interface {
	XXX_Merge(src Message)
}

// Merge merges src into dst.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
// Merge panics if src and dst are not the same type, or if dst is nil.
func (,  Message) {
	if ,  := .(Merger);  {
		.Merge()
		return
	}

	 := reflect.ValueOf()
	 := reflect.ValueOf()
	if .IsNil() {
		panic("proto: nil destination")
	}
	if .Type() != .Type() {
		panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", , ))
	}
	if .IsNil() {
		return // Merge from nil src is a noop
	}
	if ,  := .(generatedMerger);  {
		.XXX_Merge()
		return
	}
	mergeStruct(.Elem(), .Elem())
}

func mergeStruct(,  reflect.Value) {
	 := GetProperties(.Type())
	for  := 0;  < .NumField(); ++ {
		 := .Type().Field()
		if strings.HasPrefix(.Name, "XXX_") {
			continue
		}
		mergeAny(.Field(), .Field(), false, .Prop[])
	}

	if ,  := .Addr().Interface().(extensionsBytes);  {
		 := .Addr().Interface().(extensionsBytes)
		 := .GetExtensions()
		 := .GetExtensions()
		* = append(*, *...)
	} else if ,  := extendable(.Addr().Interface());  == nil {
		,  := extendable(.Addr().Interface())
		,  := .extensionsRead()
		if  != nil {
			 := .extensionsWrite()
			.Lock()
			mergeExtension(, )
			.Unlock()
		}
	}

	 := .FieldByName("XXX_unrecognized")
	if !.IsValid() {
		return
	}
	 := .Bytes()
	if len() > 0 {
		.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), ...))
	}
}

// mergeAny performs a merge between two values of the same type.
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
// prop is set if this is a struct field (it may be nil).
func mergeAny(,  reflect.Value,  bool,  *Properties) {
	if .Type() == protoMessageType {
		if !.IsNil() {
			if .IsNil() {
				.Set(reflect.ValueOf(Clone(.Interface().(Message))))
			} else {
				Merge(.Interface().(Message), .Interface().(Message))
			}
		}
		return
	}
	switch .Kind() {
	case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
		reflect.String, reflect.Uint32, reflect.Uint64:
		if ! && isProto3Zero() {
			return
		}
		.Set()
	case reflect.Interface:
		// Probably a oneof field; copy non-nil values.
		if .IsNil() {
			return
		}
		// Allocate destination if it is not set, or set to a different type.
		// Otherwise we will merge as normal.
		if .IsNil() || .Elem().Type() != .Elem().Type() {
			.Set(reflect.New(.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
		}
		(.Elem(), .Elem(), false, nil)
	case reflect.Map:
		if .Len() == 0 {
			return
		}
		if .IsNil() {
			.Set(reflect.MakeMap(.Type()))
		}
		// For maps with value types of *T or []byte we need to deep copy each value.
		 := .Type().Elem().Kind()
		for ,  := range .MapKeys() {
			var  reflect.Value
			switch  {
			case reflect.Ptr:
				 = reflect.New(.Type().Elem().Elem())
				(, .MapIndex(), false, nil)
			case reflect.Slice:
				 = .MapIndex()
				 = reflect.ValueOf(append([]byte{}, .Bytes()...))
			default:
				 = .MapIndex()
			}
			.SetMapIndex(, )
		}
	case reflect.Ptr:
		if .IsNil() {
			return
		}
		if .IsNil() {
			.Set(reflect.New(.Elem().Type()))
		}
		(.Elem(), .Elem(), true, nil)
	case reflect.Slice:
		if .IsNil() {
			return
		}
		if .Type().Elem().Kind() == reflect.Uint8 {
			// []byte is a scalar bytes field, not a repeated field.

			// Edge case: if this is in a proto3 message, a zero length
			// bytes field is considered the zero value, and should not
			// be merged.
			if  != nil && .proto3 && .Len() == 0 {
				return
			}

			// Make a deep copy.
			// Append to []byte{} instead of []byte(nil) so that we never end up
			// with a nil result.
			.SetBytes(append([]byte{}, .Bytes()...))
			return
		}
		 := .Len()
		if .IsNil() {
			.Set(reflect.MakeSlice(.Type(), 0, ))
		}
		switch .Type().Elem().Kind() {
		case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
			reflect.String, reflect.Uint32, reflect.Uint64:
			.Set(reflect.AppendSlice(, ))
		default:
			for  := 0;  < ; ++ {
				 := reflect.Indirect(reflect.New(.Type().Elem()))
				(, .Index(), false, nil)
				.Set(reflect.Append(, ))
			}
		}
	case reflect.Struct:
		mergeStruct(, )
	default:
		// unknown type, so not a protocol buffer
		log.Printf("proto: don't know how to copy %v", )
	}
}

func mergeExtension(,  map[int32]Extension) {
	for ,  := range  {
		 := Extension{desc: .desc}
		if .value != nil {
			 := reflect.New(reflect.TypeOf(.value)).Elem()
			mergeAny(, reflect.ValueOf(.value), false, nil)
			.value = .Interface()
		}
		if .enc != nil {
			.enc = make([]byte, len(.enc))
			copy(.enc, .enc)
		}

		[] = 
	}
}