-
Notifications
You must be signed in to change notification settings - Fork 3
/
utils.go
103 lines (84 loc) · 2.43 KB
/
utils.go
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package bigproto
import (
"errors"
"fmt"
"reflect"
"dario.cat/mergo"
"github.com/mennanov/fmutils"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/fieldmaskpb"
)
// ErrNotFound is returned when the desired resource is not found in Bigtable.
type ErrNotFound struct {
RowKey string // unavailable locations
}
func (e ErrNotFound) Error() string {
return fmt.Sprintf("%s not found", e.RowKey)
}
var ErrInvalidFieldMask = errors.New("invalid field mask")
type ErrMismatchedTypes struct {
Expected reflect.Type
Actual reflect.Type
}
func (e ErrMismatchedTypes) Error() string {
return fmt.Sprintf("expected %s, got %s", e.Expected, e.Actual)
}
type ErrInvalidNextToken struct {
nextToken string
}
func (e ErrInvalidNextToken) Error() string {
return fmt.Sprintf("invalid nextToken (%s)", e.nextToken)
}
type ErrNegativePageSize struct{}
func (e ErrNegativePageSize) Error() string {
return "page size cannot be less than 0"
}
// newEmptyMessage returns a new instance of the same type as the provided proto.Message
func newEmptyMessage(msg proto.Message) proto.Message {
// Get the reflect.Type of the message
msgType := reflect.TypeOf(msg)
if msgType.Kind() == reflect.Ptr {
msgType = msgType.Elem()
}
// Create a new instance of the message type using reflection
newMsg := reflect.New(msgType).Interface().(proto.Message)
return newMsg
}
// mergeUpdates merges the updates into the current message in line with the update mask
func mergeUpdates(current proto.Message, updates proto.Message, updateMask *fieldmaskpb.FieldMask) error {
// If current and updates are different types, return an error
if reflect.TypeOf(current) != reflect.TypeOf(updates) {
return ErrMismatchedTypes{
Expected: reflect.TypeOf(current),
Actual: reflect.TypeOf(updates),
}
}
// If updates is nil, return nil
if updates == nil {
return nil
}
// If current is nil, return updates
if current == nil {
current = updates
return nil
}
// If updates is empty, return nil
if proto.Size(updates) == 0 {
return nil
}
// Apply Update Mask if provided
if updateMask != nil {
updateMask.Normalize()
if !updateMask.IsValid(current) {
return ErrInvalidFieldMask
}
// Redact the request according to the provided field mask.
fmutils.Prune(current, updateMask.GetPaths())
}
// Merge the updates into the current message
err := mergo.Merge(current, updates)
if err != nil {
return err
}
return nil
}