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 }