1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package proto
33
34 import (
35 "fmt"
36 "reflect"
37 "strings"
38 "sync"
39 "sync/atomic"
40 )
41
42
43
44 func (a *InternalMessageInfo) Merge(dst, src Message) {
45 mi := atomicLoadMergeInfo(&a.merge)
46 if mi == nil {
47 mi = getMergeInfo(reflect.TypeOf(dst).Elem())
48 atomicStoreMergeInfo(&a.merge, mi)
49 }
50 mi.merge(toPointer(&dst), toPointer(&src))
51 }
52
53 type mergeInfo struct {
54 typ reflect.Type
55
56 initialized int32
57 lock sync.Mutex
58
59 fields []mergeFieldInfo
60 unrecognized field
61 }
62
63 type mergeFieldInfo struct {
64 field field
65
66
67
68
69
70
71
72 isPointer bool
73
74
75
76
77
78
79
80
81 basicWidth int
82
83
84 merge func(dst, src pointer)
85 }
86
87 var (
88 mergeInfoMap = map[reflect.Type]*mergeInfo{}
89 mergeInfoLock sync.Mutex
90 )
91
92 func getMergeInfo(t reflect.Type) *mergeInfo {
93 mergeInfoLock.Lock()
94 defer mergeInfoLock.Unlock()
95 mi := mergeInfoMap[t]
96 if mi == nil {
97 mi = &mergeInfo{typ: t}
98 mergeInfoMap[t] = mi
99 }
100 return mi
101 }
102
103
104 func (mi *mergeInfo) merge(dst, src pointer) {
105 if dst.isNil() {
106 panic("proto: nil destination")
107 }
108 if src.isNil() {
109 return
110 }
111
112 if atomic.LoadInt32(&mi.initialized) == 0 {
113 mi.computeMergeInfo()
114 }
115
116 for _, fi := range mi.fields {
117 sfp := src.offset(fi.field)
118
119
120
121
122 if unsafeAllowed {
123 if fi.isPointer && sfp.getPointer().isNil() {
124 continue
125 }
126 if fi.basicWidth > 0 {
127 switch {
128 case fi.basicWidth == 1 && !*sfp.toBool():
129 continue
130 case fi.basicWidth == 4 && *sfp.toUint32() == 0:
131 continue
132 case fi.basicWidth == 8 && *sfp.toUint64() == 0:
133 continue
134 }
135 }
136 }
137
138 dfp := dst.offset(fi.field)
139 fi.merge(dfp, sfp)
140 }
141
142
143 out := dst.asPointerTo(mi.typ).Elem()
144 in := src.asPointerTo(mi.typ).Elem()
145 if emIn, err := extendable(in.Addr().Interface()); err == nil {
146 emOut, _ := extendable(out.Addr().Interface())
147 mIn, muIn := emIn.extensionsRead()
148 if mIn != nil {
149 mOut := emOut.extensionsWrite()
150 muIn.Lock()
151 mergeExtension(mOut, mIn)
152 muIn.Unlock()
153 }
154 }
155
156 if mi.unrecognized.IsValid() {
157 if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
158 *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
159 }
160 }
161 }
162
163 func (mi *mergeInfo) computeMergeInfo() {
164 mi.lock.Lock()
165 defer mi.lock.Unlock()
166 if mi.initialized != 0 {
167 return
168 }
169 t := mi.typ
170 n := t.NumField()
171
172 props := GetProperties(t)
173 for i := 0; i < n; i++ {
174 f := t.Field(i)
175 if strings.HasPrefix(f.Name, "XXX_") {
176 continue
177 }
178
179 mfi := mergeFieldInfo{field: toField(&f)}
180 tf := f.Type
181
182
183
184
185 if unsafeAllowed {
186 switch tf.Kind() {
187 case reflect.Ptr, reflect.Slice, reflect.String:
188
189
190
191 mfi.isPointer = true
192 case reflect.Bool:
193 mfi.basicWidth = 1
194 case reflect.Int32, reflect.Uint32, reflect.Float32:
195 mfi.basicWidth = 4
196 case reflect.Int64, reflect.Uint64, reflect.Float64:
197 mfi.basicWidth = 8
198 }
199 }
200
201
202 var isPointer, isSlice bool
203 if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
204 isSlice = true
205 tf = tf.Elem()
206 }
207 if tf.Kind() == reflect.Ptr {
208 isPointer = true
209 tf = tf.Elem()
210 }
211 if isPointer && isSlice && tf.Kind() != reflect.Struct {
212 panic("both pointer and slice for basic type in " + tf.Name())
213 }
214
215 switch tf.Kind() {
216 case reflect.Int32:
217 switch {
218 case isSlice:
219 mfi.merge = func(dst, src pointer) {
220
221
231 sfs := src.getInt32Slice()
232 if sfs != nil {
233 dfs := dst.getInt32Slice()
234 dfs = append(dfs, sfs...)
235 if dfs == nil {
236 dfs = []int32{}
237 }
238 dst.setInt32Slice(dfs)
239 }
240 }
241 case isPointer:
242 mfi.merge = func(dst, src pointer) {
243
244
255 sfp := src.getInt32Ptr()
256 if sfp != nil {
257 dfp := dst.getInt32Ptr()
258 if dfp == nil {
259 dst.setInt32Ptr(*sfp)
260 } else {
261 *dfp = *sfp
262 }
263 }
264 }
265 default:
266 mfi.merge = func(dst, src pointer) {
267 if v := *src.toInt32(); v != 0 {
268 *dst.toInt32() = v
269 }
270 }
271 }
272 case reflect.Int64:
273 switch {
274 case isSlice:
275 mfi.merge = func(dst, src pointer) {
276 sfsp := src.toInt64Slice()
277 if *sfsp != nil {
278 dfsp := dst.toInt64Slice()
279 *dfsp = append(*dfsp, *sfsp...)
280 if *dfsp == nil {
281 *dfsp = []int64{}
282 }
283 }
284 }
285 case isPointer:
286 mfi.merge = func(dst, src pointer) {
287 sfpp := src.toInt64Ptr()
288 if *sfpp != nil {
289 dfpp := dst.toInt64Ptr()
290 if *dfpp == nil {
291 *dfpp = Int64(**sfpp)
292 } else {
293 **dfpp = **sfpp
294 }
295 }
296 }
297 default:
298 mfi.merge = func(dst, src pointer) {
299 if v := *src.toInt64(); v != 0 {
300 *dst.toInt64() = v
301 }
302 }
303 }
304 case reflect.Uint32:
305 switch {
306 case isSlice:
307 mfi.merge = func(dst, src pointer) {
308 sfsp := src.toUint32Slice()
309 if *sfsp != nil {
310 dfsp := dst.toUint32Slice()
311 *dfsp = append(*dfsp, *sfsp...)
312 if *dfsp == nil {
313 *dfsp = []uint32{}
314 }
315 }
316 }
317 case isPointer:
318 mfi.merge = func(dst, src pointer) {
319 sfpp := src.toUint32Ptr()
320 if *sfpp != nil {
321 dfpp := dst.toUint32Ptr()
322 if *dfpp == nil {
323 *dfpp = Uint32(**sfpp)
324 } else {
325 **dfpp = **sfpp
326 }
327 }
328 }
329 default:
330 mfi.merge = func(dst, src pointer) {
331 if v := *src.toUint32(); v != 0 {
332 *dst.toUint32() = v
333 }
334 }
335 }
336 case reflect.Uint64:
337 switch {
338 case isSlice:
339 mfi.merge = func(dst, src pointer) {
340 sfsp := src.toUint64Slice()
341 if *sfsp != nil {
342 dfsp := dst.toUint64Slice()
343 *dfsp = append(*dfsp, *sfsp...)
344 if *dfsp == nil {
345 *dfsp = []uint64{}
346 }
347 }
348 }
349 case isPointer:
350 mfi.merge = func(dst, src pointer) {
351 sfpp := src.toUint64Ptr()
352 if *sfpp != nil {
353 dfpp := dst.toUint64Ptr()
354 if *dfpp == nil {
355 *dfpp = Uint64(**sfpp)
356 } else {
357 **dfpp = **sfpp
358 }
359 }
360 }
361 default:
362 mfi.merge = func(dst, src pointer) {
363 if v := *src.toUint64(); v != 0 {
364 *dst.toUint64() = v
365 }
366 }
367 }
368 case reflect.Float32:
369 switch {
370 case isSlice:
371 mfi.merge = func(dst, src pointer) {
372 sfsp := src.toFloat32Slice()
373 if *sfsp != nil {
374 dfsp := dst.toFloat32Slice()
375 *dfsp = append(*dfsp, *sfsp...)
376 if *dfsp == nil {
377 *dfsp = []float32{}
378 }
379 }
380 }
381 case isPointer:
382 mfi.merge = func(dst, src pointer) {
383 sfpp := src.toFloat32Ptr()
384 if *sfpp != nil {
385 dfpp := dst.toFloat32Ptr()
386 if *dfpp == nil {
387 *dfpp = Float32(**sfpp)
388 } else {
389 **dfpp = **sfpp
390 }
391 }
392 }
393 default:
394 mfi.merge = func(dst, src pointer) {
395 if v := *src.toFloat32(); v != 0 {
396 *dst.toFloat32() = v
397 }
398 }
399 }
400 case reflect.Float64:
401 switch {
402 case isSlice:
403 mfi.merge = func(dst, src pointer) {
404 sfsp := src.toFloat64Slice()
405 if *sfsp != nil {
406 dfsp := dst.toFloat64Slice()
407 *dfsp = append(*dfsp, *sfsp...)
408 if *dfsp == nil {
409 *dfsp = []float64{}
410 }
411 }
412 }
413 case isPointer:
414 mfi.merge = func(dst, src pointer) {
415 sfpp := src.toFloat64Ptr()
416 if *sfpp != nil {
417 dfpp := dst.toFloat64Ptr()
418 if *dfpp == nil {
419 *dfpp = Float64(**sfpp)
420 } else {
421 **dfpp = **sfpp
422 }
423 }
424 }
425 default:
426 mfi.merge = func(dst, src pointer) {
427 if v := *src.toFloat64(); v != 0 {
428 *dst.toFloat64() = v
429 }
430 }
431 }
432 case reflect.Bool:
433 switch {
434 case isSlice:
435 mfi.merge = func(dst, src pointer) {
436 sfsp := src.toBoolSlice()
437 if *sfsp != nil {
438 dfsp := dst.toBoolSlice()
439 *dfsp = append(*dfsp, *sfsp...)
440 if *dfsp == nil {
441 *dfsp = []bool{}
442 }
443 }
444 }
445 case isPointer:
446 mfi.merge = func(dst, src pointer) {
447 sfpp := src.toBoolPtr()
448 if *sfpp != nil {
449 dfpp := dst.toBoolPtr()
450 if *dfpp == nil {
451 *dfpp = Bool(**sfpp)
452 } else {
453 **dfpp = **sfpp
454 }
455 }
456 }
457 default:
458 mfi.merge = func(dst, src pointer) {
459 if v := *src.toBool(); v {
460 *dst.toBool() = v
461 }
462 }
463 }
464 case reflect.String:
465 switch {
466 case isSlice:
467 mfi.merge = func(dst, src pointer) {
468 sfsp := src.toStringSlice()
469 if *sfsp != nil {
470 dfsp := dst.toStringSlice()
471 *dfsp = append(*dfsp, *sfsp...)
472 if *dfsp == nil {
473 *dfsp = []string{}
474 }
475 }
476 }
477 case isPointer:
478 mfi.merge = func(dst, src pointer) {
479 sfpp := src.toStringPtr()
480 if *sfpp != nil {
481 dfpp := dst.toStringPtr()
482 if *dfpp == nil {
483 *dfpp = String(**sfpp)
484 } else {
485 **dfpp = **sfpp
486 }
487 }
488 }
489 default:
490 mfi.merge = func(dst, src pointer) {
491 if v := *src.toString(); v != "" {
492 *dst.toString() = v
493 }
494 }
495 }
496 case reflect.Slice:
497 isProto3 := props.Prop[i].proto3
498 switch {
499 case isPointer:
500 panic("bad pointer in byte slice case in " + tf.Name())
501 case tf.Elem().Kind() != reflect.Uint8:
502 panic("bad element kind in byte slice case in " + tf.Name())
503 case isSlice:
504 mfi.merge = func(dst, src pointer) {
505 sbsp := src.toBytesSlice()
506 if *sbsp != nil {
507 dbsp := dst.toBytesSlice()
508 for _, sb := range *sbsp {
509 if sb == nil {
510 *dbsp = append(*dbsp, nil)
511 } else {
512 *dbsp = append(*dbsp, append([]byte{}, sb...))
513 }
514 }
515 if *dbsp == nil {
516 *dbsp = [][]byte{}
517 }
518 }
519 }
520 default:
521 mfi.merge = func(dst, src pointer) {
522 sbp := src.toBytes()
523 if *sbp != nil {
524 dbp := dst.toBytes()
525 if !isProto3 || len(*sbp) > 0 {
526 *dbp = append([]byte{}, *sbp...)
527 }
528 }
529 }
530 }
531 case reflect.Struct:
532 switch {
533 case isSlice && !isPointer:
534 mergeInfo := getMergeInfo(tf)
535 zero := reflect.Zero(tf)
536 mfi.merge = func(dst, src pointer) {
537
538 dstsp := dst.asPointerTo(f.Type)
539 dsts := dstsp.Elem()
540 srcs := src.asPointerTo(f.Type).Elem()
541 for i := 0; i < srcs.Len(); i++ {
542 dsts = reflect.Append(dsts, zero)
543 srcElement := srcs.Index(i).Addr()
544 dstElement := dsts.Index(dsts.Len() - 1).Addr()
545 mergeInfo.merge(valToPointer(dstElement), valToPointer(srcElement))
546 }
547 if dsts.IsNil() {
548 dsts = reflect.MakeSlice(f.Type, 0, 0)
549 }
550 dstsp.Elem().Set(dsts)
551 }
552 case !isPointer:
553 mergeInfo := getMergeInfo(tf)
554 mfi.merge = func(dst, src pointer) {
555 mergeInfo.merge(dst, src)
556 }
557 case isSlice:
558 mergeInfo := getMergeInfo(tf)
559 mfi.merge = func(dst, src pointer) {
560 sps := src.getPointerSlice()
561 if sps != nil {
562 dps := dst.getPointerSlice()
563 for _, sp := range sps {
564 var dp pointer
565 if !sp.isNil() {
566 dp = valToPointer(reflect.New(tf))
567 mergeInfo.merge(dp, sp)
568 }
569 dps = append(dps, dp)
570 }
571 if dps == nil {
572 dps = []pointer{}
573 }
574 dst.setPointerSlice(dps)
575 }
576 }
577 default:
578 mergeInfo := getMergeInfo(tf)
579 mfi.merge = func(dst, src pointer) {
580 sp := src.getPointer()
581 if !sp.isNil() {
582 dp := dst.getPointer()
583 if dp.isNil() {
584 dp = valToPointer(reflect.New(tf))
585 dst.setPointer(dp)
586 }
587 mergeInfo.merge(dp, sp)
588 }
589 }
590 }
591 case reflect.Map:
592 switch {
593 case isPointer || isSlice:
594 panic("bad pointer or slice in map case in " + tf.Name())
595 default:
596 mfi.merge = func(dst, src pointer) {
597 sm := src.asPointerTo(tf).Elem()
598 if sm.Len() == 0 {
599 return
600 }
601 dm := dst.asPointerTo(tf).Elem()
602 if dm.IsNil() {
603 dm.Set(reflect.MakeMap(tf))
604 }
605
606 switch tf.Elem().Kind() {
607 case reflect.Ptr:
608 for _, key := range sm.MapKeys() {
609 val := sm.MapIndex(key)
610 val = reflect.ValueOf(Clone(val.Interface().(Message)))
611 dm.SetMapIndex(key, val)
612 }
613 case reflect.Slice:
614 for _, key := range sm.MapKeys() {
615 val := sm.MapIndex(key)
616 val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
617 dm.SetMapIndex(key, val)
618 }
619 default:
620 for _, key := range sm.MapKeys() {
621 val := sm.MapIndex(key)
622 dm.SetMapIndex(key, val)
623 }
624 }
625 }
626 }
627 case reflect.Interface:
628
629 switch {
630 case isPointer || isSlice:
631 panic("bad pointer or slice in interface case in " + tf.Name())
632 default:
633
634 mfi.merge = func(dst, src pointer) {
635 su := src.asPointerTo(tf).Elem()
636 if !su.IsNil() {
637 du := dst.asPointerTo(tf).Elem()
638 typ := su.Elem().Type()
639 if du.IsNil() || du.Elem().Type() != typ {
640 du.Set(reflect.New(typ.Elem()))
641 }
642 sv := su.Elem().Elem().Field(0)
643 if sv.Kind() == reflect.Ptr && sv.IsNil() {
644 return
645 }
646 dv := du.Elem().Elem().Field(0)
647 if dv.Kind() == reflect.Ptr && dv.IsNil() {
648 dv.Set(reflect.New(sv.Type().Elem()))
649 }
650 switch sv.Type().Kind() {
651 case reflect.Ptr:
652 Merge(dv.Interface().(Message), sv.Interface().(Message))
653 case reflect.Slice:
654 dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
655 default:
656 dv.Set(sv)
657 }
658 }
659 }
660 }
661 default:
662 panic(fmt.Sprintf("merger not found for type:%s", tf))
663 }
664 mi.fields = append(mi.fields, mfi)
665 }
666
667 mi.unrecognized = invalidField
668 if f, ok := t.FieldByName("XXX_unrecognized"); ok {
669 if f.Type != reflect.TypeOf([]byte{}) {
670 panic("expected XXX_unrecognized to be of type []byte")
671 }
672 mi.unrecognized = toField(&f)
673 }
674
675 atomic.StoreInt32(&mi.initialized, 1)
676 }
677
View as plain text