717
// MergeProtoExcludingFields merges fields from source into target, excluding specific fields.
718
// The fields to exclude are specified as pointers to fields in the target struct.
719
>
func MergeProtoExcludingFields(target, source proto.Message, doNotSyncFunc func(v any) []any) error {
util.go
720
>
if target == nil || source == nil {
721
return serviceerror.NewInvalidArgument("target and source cannot be nil")
722
}
723
724
>
if reflect.TypeOf(target) != reflect.TypeOf(source) {
util.go
725
return serviceerror.NewInvalidArgument("target and source must be of the same type")
726
}
727
728
>
excludeFields := doNotSyncFunc(target)
util.go
729
>
excludeSet := make(map[string]struct{}, len(excludeFields))
730
>
for _, fieldPtr := range excludeFields {
731
>
fieldName, err := getFieldNameFromStruct(target, fieldPtr)
732
>
if err != nil {
733
return err
734
}
735
>
excludeSet[fieldName] = struct{}{}
util.go
736
}
737
738
>
srcVal := reflect.ValueOf(source).Elem()
util.go
739
>
dstVal := reflect.ValueOf(target).Elem()
740
>
for i := 0; i < srcVal.NumField(); i++ {
741
>
field := srcVal.Type().Field(i)
742
>
if _, exclude := excludeSet[field.Name]; !exclude {
743
>
srcField := srcVal.Field(i)
744
>
dstField := dstVal.Field(i)
745
>
if dstField.CanSet() {
746
>
dstField.Set(srcField)
747
>
}
748
}
749
}
750
752
}
753
754
>
func getFieldNameFromStruct(structPtr any, fieldPtr any) (string, error) {
util.go
755
>
structVal := reflect.ValueOf(structPtr).Elem()
756
>
for i := 0; i < structVal.NumField(); i++ {
757
>
field := structVal.Field(i)
758
>
if field.CanSet() && field.Addr().Interface() == fieldPtr {
759
>
return structVal.Type().Field(i).Name, nil
760
>
}
761
}
762
return "", serviceerror.NewInternal("field not found in the struct")