1 | // Copyright 2020 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 impl
|
---|
6 |
|
---|
7 | import (
|
---|
8 | "fmt"
|
---|
9 | "reflect"
|
---|
10 |
|
---|
11 | "google.golang.org/protobuf/proto"
|
---|
12 | "google.golang.org/protobuf/reflect/protoreflect"
|
---|
13 | "google.golang.org/protobuf/runtime/protoiface"
|
---|
14 | )
|
---|
15 |
|
---|
16 | type mergeOptions struct{}
|
---|
17 |
|
---|
18 | func (o mergeOptions) Merge(dst, src proto.Message) {
|
---|
19 | proto.Merge(dst, src)
|
---|
20 | }
|
---|
21 |
|
---|
22 | // merge is protoreflect.Methods.Merge.
|
---|
23 | func (mi *MessageInfo) merge(in protoiface.MergeInput) protoiface.MergeOutput {
|
---|
24 | dp, ok := mi.getPointer(in.Destination)
|
---|
25 | if !ok {
|
---|
26 | return protoiface.MergeOutput{}
|
---|
27 | }
|
---|
28 | sp, ok := mi.getPointer(in.Source)
|
---|
29 | if !ok {
|
---|
30 | return protoiface.MergeOutput{}
|
---|
31 | }
|
---|
32 | mi.mergePointer(dp, sp, mergeOptions{})
|
---|
33 | return protoiface.MergeOutput{Flags: protoiface.MergeComplete}
|
---|
34 | }
|
---|
35 |
|
---|
36 | func (mi *MessageInfo) mergePointer(dst, src pointer, opts mergeOptions) {
|
---|
37 | mi.init()
|
---|
38 | if dst.IsNil() {
|
---|
39 | panic(fmt.Sprintf("invalid value: merging into nil message"))
|
---|
40 | }
|
---|
41 | if src.IsNil() {
|
---|
42 | return
|
---|
43 | }
|
---|
44 | for _, f := range mi.orderedCoderFields {
|
---|
45 | if f.funcs.merge == nil {
|
---|
46 | continue
|
---|
47 | }
|
---|
48 | sfptr := src.Apply(f.offset)
|
---|
49 | if f.isPointer && sfptr.Elem().IsNil() {
|
---|
50 | continue
|
---|
51 | }
|
---|
52 | f.funcs.merge(dst.Apply(f.offset), sfptr, f, opts)
|
---|
53 | }
|
---|
54 | if mi.extensionOffset.IsValid() {
|
---|
55 | sext := src.Apply(mi.extensionOffset).Extensions()
|
---|
56 | dext := dst.Apply(mi.extensionOffset).Extensions()
|
---|
57 | if *dext == nil {
|
---|
58 | *dext = make(map[int32]ExtensionField)
|
---|
59 | }
|
---|
60 | for num, sx := range *sext {
|
---|
61 | xt := sx.Type()
|
---|
62 | xi := getExtensionFieldInfo(xt)
|
---|
63 | if xi.funcs.merge == nil {
|
---|
64 | continue
|
---|
65 | }
|
---|
66 | dx := (*dext)[num]
|
---|
67 | var dv protoreflect.Value
|
---|
68 | if dx.Type() == sx.Type() {
|
---|
69 | dv = dx.Value()
|
---|
70 | }
|
---|
71 | if !dv.IsValid() && xi.unmarshalNeedsValue {
|
---|
72 | dv = xt.New()
|
---|
73 | }
|
---|
74 | dv = xi.funcs.merge(dv, sx.Value(), opts)
|
---|
75 | dx.Set(sx.Type(), dv)
|
---|
76 | (*dext)[num] = dx
|
---|
77 | }
|
---|
78 | }
|
---|
79 | if mi.unknownOffset.IsValid() {
|
---|
80 | su := mi.getUnknownBytes(src)
|
---|
81 | if su != nil && len(*su) > 0 {
|
---|
82 | du := mi.mutableUnknownBytes(dst)
|
---|
83 | *du = append(*du, *su...)
|
---|
84 | }
|
---|
85 | }
|
---|
86 | }
|
---|
87 |
|
---|
88 | func mergeScalarValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
89 | return src
|
---|
90 | }
|
---|
91 |
|
---|
92 | func mergeBytesValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
93 | return protoreflect.ValueOfBytes(append(emptyBuf[:], src.Bytes()...))
|
---|
94 | }
|
---|
95 |
|
---|
96 | func mergeListValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
97 | dstl := dst.List()
|
---|
98 | srcl := src.List()
|
---|
99 | for i, llen := 0, srcl.Len(); i < llen; i++ {
|
---|
100 | dstl.Append(srcl.Get(i))
|
---|
101 | }
|
---|
102 | return dst
|
---|
103 | }
|
---|
104 |
|
---|
105 | func mergeBytesListValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
106 | dstl := dst.List()
|
---|
107 | srcl := src.List()
|
---|
108 | for i, llen := 0, srcl.Len(); i < llen; i++ {
|
---|
109 | sb := srcl.Get(i).Bytes()
|
---|
110 | db := append(emptyBuf[:], sb...)
|
---|
111 | dstl.Append(protoreflect.ValueOfBytes(db))
|
---|
112 | }
|
---|
113 | return dst
|
---|
114 | }
|
---|
115 |
|
---|
116 | func mergeMessageListValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
117 | dstl := dst.List()
|
---|
118 | srcl := src.List()
|
---|
119 | for i, llen := 0, srcl.Len(); i < llen; i++ {
|
---|
120 | sm := srcl.Get(i).Message()
|
---|
121 | dm := proto.Clone(sm.Interface()).ProtoReflect()
|
---|
122 | dstl.Append(protoreflect.ValueOfMessage(dm))
|
---|
123 | }
|
---|
124 | return dst
|
---|
125 | }
|
---|
126 |
|
---|
127 | func mergeMessageValue(dst, src protoreflect.Value, opts mergeOptions) protoreflect.Value {
|
---|
128 | opts.Merge(dst.Message().Interface(), src.Message().Interface())
|
---|
129 | return dst
|
---|
130 | }
|
---|
131 |
|
---|
132 | func mergeMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
|
---|
133 | if f.mi != nil {
|
---|
134 | if dst.Elem().IsNil() {
|
---|
135 | dst.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
|
---|
136 | }
|
---|
137 | f.mi.mergePointer(dst.Elem(), src.Elem(), opts)
|
---|
138 | } else {
|
---|
139 | dm := dst.AsValueOf(f.ft).Elem()
|
---|
140 | sm := src.AsValueOf(f.ft).Elem()
|
---|
141 | if dm.IsNil() {
|
---|
142 | dm.Set(reflect.New(f.ft.Elem()))
|
---|
143 | }
|
---|
144 | opts.Merge(asMessage(dm), asMessage(sm))
|
---|
145 | }
|
---|
146 | }
|
---|
147 |
|
---|
148 | func mergeMessageSlice(dst, src pointer, f *coderFieldInfo, opts mergeOptions) {
|
---|
149 | for _, sp := range src.PointerSlice() {
|
---|
150 | dm := reflect.New(f.ft.Elem().Elem())
|
---|
151 | if f.mi != nil {
|
---|
152 | f.mi.mergePointer(pointerOfValue(dm), sp, opts)
|
---|
153 | } else {
|
---|
154 | opts.Merge(asMessage(dm), asMessage(sp.AsValueOf(f.ft.Elem().Elem())))
|
---|
155 | }
|
---|
156 | dst.AppendPointerSlice(pointerOfValue(dm))
|
---|
157 | }
|
---|
158 | }
|
---|
159 |
|
---|
160 | func mergeBytes(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
|
---|
161 | *dst.Bytes() = append(emptyBuf[:], *src.Bytes()...)
|
---|
162 | }
|
---|
163 |
|
---|
164 | func mergeBytesNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
|
---|
165 | v := *src.Bytes()
|
---|
166 | if len(v) > 0 {
|
---|
167 | *dst.Bytes() = append(emptyBuf[:], v...)
|
---|
168 | }
|
---|
169 | }
|
---|
170 |
|
---|
171 | func mergeBytesSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
|
---|
172 | ds := dst.BytesSlice()
|
---|
173 | for _, v := range *src.BytesSlice() {
|
---|
174 | *ds = append(*ds, append(emptyBuf[:], v...))
|
---|
175 | }
|
---|
176 | }
|
---|