github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/google.golang.org/protobuf/proto/merge.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package proto
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"google.golang.org/protobuf/reflect/protoreflect"
    11  	"google.golang.org/protobuf/runtime/protoiface"
    12  )
    13  
    14  // Merge merges src into dst, which must be a message with the same descriptor.
    15  //
    16  // Populated scalar fields in src are copied to dst, while populated
    17  // singular messages in src are merged into dst by recursively calling Merge.
    18  // The elements of every list field in src is appended to the corresponded
    19  // list fields in dst. The entries of every map field in src is copied into
    20  // the corresponding map field in dst, possibly replacing existing entries.
    21  // The unknown fields of src are appended to the unknown fields of dst.
    22  //
    23  // It is semantically equivalent to unmarshaling the encoded form of src
    24  // into dst with the UnmarshalOptions.Merge option specified.
    25  func Merge(dst, src Message) {
    26  	// TODO: Should nil src be treated as semantically equivalent to a
    27  	// untyped, read-only, empty message? What about a nil dst?
    28  
    29  	dstMsg, srcMsg := dst.ProtoReflect(), src.ProtoReflect()
    30  	if dstMsg.Descriptor() != srcMsg.Descriptor() {
    31  		if got, want := dstMsg.Descriptor().FullName(), srcMsg.Descriptor().FullName(); got != want {
    32  			panic(fmt.Sprintf("descriptor mismatch: %v != %v", got, want))
    33  		}
    34  		panic("descriptor mismatch")
    35  	}
    36  	mergeOptions{}.mergeMessage(dstMsg, srcMsg)
    37  }
    38  
    39  // Clone returns a deep copy of m.
    40  // If the top-level message is invalid, it returns an invalid message as well.
    41  func Clone(m Message) Message {
    42  	// NOTE: Most usages of Clone assume the following properties:
    43  	//	t := reflect.TypeOf(m)
    44  	//	t == reflect.TypeOf(m.ProtoReflect().New().Interface())
    45  	//	t == reflect.TypeOf(m.ProtoReflect().Type().Zero().Interface())
    46  	//
    47  	// Embedding protobuf messages breaks this since the parent type will have
    48  	// a forwarded ProtoReflect method, but the Interface method will return
    49  	// the underlying embedded message type.
    50  	if m == nil {
    51  		return nil
    52  	}
    53  	src := m.ProtoReflect()
    54  	if !src.IsValid() {
    55  		return src.Type().Zero().Interface()
    56  	}
    57  	dst := src.New()
    58  	mergeOptions{}.mergeMessage(dst, src)
    59  	return dst.Interface()
    60  }
    61  
    62  // mergeOptions provides a namespace for merge functions, and can be
    63  // exported in the future if we add user-visible merge options.
    64  type mergeOptions struct{}
    65  
    66  func (o mergeOptions) mergeMessage(dst, src protoreflect.Message) {
    67  	methods := protoMethods(dst)
    68  	if methods != nil && methods.Merge != nil {
    69  		in := protoiface.MergeInput{
    70  			Destination: dst,
    71  			Source:      src,
    72  		}
    73  		out := methods.Merge(in)
    74  		if out.Flags&protoiface.MergeComplete != 0 {
    75  			return
    76  		}
    77  	}
    78  
    79  	if !dst.IsValid() {
    80  		panic(fmt.Sprintf("cannot merge into invalid %v message", dst.Descriptor().FullName()))
    81  	}
    82  
    83  	src.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
    84  		switch {
    85  		case fd.IsList():
    86  			o.mergeList(dst.Mutable(fd).List(), v.List(), fd)
    87  		case fd.IsMap():
    88  			o.mergeMap(dst.Mutable(fd).Map(), v.Map(), fd.MapValue())
    89  		case fd.Message() != nil:
    90  			o.mergeMessage(dst.Mutable(fd).Message(), v.Message())
    91  		case fd.Kind() == protoreflect.BytesKind:
    92  			dst.Set(fd, o.cloneBytes(v))
    93  		default:
    94  			dst.Set(fd, v)
    95  		}
    96  		return true
    97  	})
    98  
    99  	if len(src.GetUnknown()) > 0 {
   100  		dst.SetUnknown(append(dst.GetUnknown(), src.GetUnknown()...))
   101  	}
   102  }
   103  
   104  func (o mergeOptions) mergeList(dst, src protoreflect.List, fd protoreflect.FieldDescriptor) {
   105  	// Merge semantics appends to the end of the existing list.
   106  	for i, n := 0, src.Len(); i < n; i++ {
   107  		switch v := src.Get(i); {
   108  		case fd.Message() != nil:
   109  			dstv := dst.NewElement()
   110  			o.mergeMessage(dstv.Message(), v.Message())
   111  			dst.Append(dstv)
   112  		case fd.Kind() == protoreflect.BytesKind:
   113  			dst.Append(o.cloneBytes(v))
   114  		default:
   115  			dst.Append(v)
   116  		}
   117  	}
   118  }
   119  
   120  func (o mergeOptions) mergeMap(dst, src protoreflect.Map, fd protoreflect.FieldDescriptor) {
   121  	// Merge semantics replaces, rather than merges into existing entries.
   122  	src.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
   123  		switch {
   124  		case fd.Message() != nil:
   125  			dstv := dst.NewValue()
   126  			o.mergeMessage(dstv.Message(), v.Message())
   127  			dst.Set(k, dstv)
   128  		case fd.Kind() == protoreflect.BytesKind:
   129  			dst.Set(k, o.cloneBytes(v))
   130  		default:
   131  			dst.Set(k, v)
   132  		}
   133  		return true
   134  	})
   135  }
   136  
   137  func (o mergeOptions) cloneBytes(v protoreflect.Value) protoreflect.Value {
   138  	return protoreflect.ValueOfBytes(append([]byte{}, v.Bytes()...))
   139  }