File: fieldmask_helper.go

package info (click to toggle)
golang-github-grpc-ecosystem-grpc-gateway 2.20.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,236 kB
  • sloc: javascript: 357; makefile: 147; sh: 26
file content (40 lines) | stat: -rw-r--r-- 1,137 bytes parent folder | download
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
33
34
35
36
37
38
39
40
package server

import (
	"strings"

	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	field_mask "google.golang.org/protobuf/types/known/fieldmaskpb"
)

func applyFieldMask(patchee, patcher proto.Message, mask *field_mask.FieldMask) {
	if mask == nil {
		return
	}
	if patchee.ProtoReflect().Descriptor().FullName() != patcher.ProtoReflect().Descriptor().FullName() {
		panic("patchee and patcher must be same type")
	}

	for _, path := range mask.GetPaths() {
		patcherField, patcherParent := getField(patcher.ProtoReflect(), path)
		patcheeField, patcheeParent := getField(patchee.ProtoReflect(), path)
		patcheeParent.Set(patcheeField, patcherParent.Get(patcherField))
	}
}

func getField(msg protoreflect.Message, path string) (field protoreflect.FieldDescriptor, parent protoreflect.Message) {
	fields := msg.Descriptor().Fields()
	parent = msg
	names := strings.Split(path, ".")
	for i, name := range names {
		field = fields.ByName(protoreflect.Name(name))

		if i < len(names)-1 {
			parent = parent.Get(field).Message()
			fields = field.Message().Fields()
		}
	}

	return field, parent
}