...
1 package server
2
3 import (
4 "log"
5 "reflect"
6 "strings"
7
8 "github.com/grpc-ecosystem/grpc-gateway/internal/casing"
9 "google.golang.org/genproto/protobuf/field_mask"
10 )
11
12 func applyFieldMask(patchee, patcher interface{}, mask *field_mask.FieldMask) {
13 if mask == nil {
14 return
15 }
16
17 for _, path := range mask.GetPaths() {
18 val := getField(patcher, path)
19 if val.IsValid() {
20 setValue(patchee, val, path)
21 }
22 }
23 }
24
25 func getField(obj interface{}, path string) (val reflect.Value) {
26
27 defer func() {
28 if r := recover(); r != nil {
29 log.Printf("failed to get field:\npath: %q\nobj: %#v\nerr: %v", path, obj, r)
30 val = reflect.Value{}
31 }
32 }()
33
34 v := reflect.ValueOf(obj)
35 if len(path) == 0 {
36 return v
37 }
38
39 for _, s := range strings.Split(path, ".") {
40 if v.Kind() == reflect.Ptr {
41 v = reflect.Indirect(v)
42 }
43 v = v.FieldByName(casing.Camel(s))
44 }
45
46 return v
47 }
48
49 func setValue(obj interface{}, newValue reflect.Value, path string) {
50 defer func() {
51 if r := recover(); r != nil {
52 log.Printf("failed to set value:\nnewValue: %#v\npath: %q\nobj: %#v\nerr: %v", newValue, path, obj, r)
53 }
54 }()
55 getField(obj, path).Set(newValue)
56 }
57
View as plain text