-
Notifications
You must be signed in to change notification settings - Fork 0
/
hooks.go
91 lines (81 loc) · 2.3 KB
/
hooks.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
package cache
// CompressionHook is a function type that is invoked prior to compressing or
// decompressing data.
type CompressionHook func(data []byte) ([]byte, error)
// Hook is an interface type defining the operations that can be intercepted
// and potentially allow for their behavior to be modified.
//
// The primary intention of Hook is to allow for observability: instrumentation,
// logging, tracing, etc.
//
// It is important implementations of Hook call next or the execution pipeline
// will terminate.
type Hook interface {
MarshalHook(next Marshaller) Marshaller
UnmarshallHook(next Unmarshaller) Unmarshaller
CompressHook(next CompressionHook) CompressionHook
DecompressHook(next CompressionHook) CompressionHook
}
type hooksMixin struct {
hooks []Hook
initial hooks
current hooks
}
// AddHook adds a Hook to the processing chain.
func (hs *hooksMixin) AddHook(hook Hook) {
hs.hooks = append(hs.hooks, hook)
hs.chain()
}
func (hs *hooksMixin) initHooks(hooks hooks) {
hs.initial = hooks
hs.chain()
}
func (hs *hooksMixin) chain() {
hs.initial.setDefaults()
hs.current.marshal = hs.initial.marshal
hs.current.unmarshall = hs.initial.unmarshall
hs.current.compress = hs.initial.compress
hs.current.decompress = hs.initial.decompress
for i := len(hs.hooks) - 1; i >= 0; i-- {
if wrapped := hs.hooks[i].MarshalHook(hs.current.marshal); wrapped != nil {
hs.current.marshal = wrapped
}
if wrapped := hs.hooks[i].UnmarshallHook(hs.current.unmarshall); wrapped != nil {
hs.current.unmarshall = wrapped
}
if wrapped := hs.hooks[i].CompressHook(hs.current.compress); wrapped != nil {
hs.current.compress = wrapped
}
if wrapped := hs.hooks[i].DecompressHook(hs.current.decompress); wrapped != nil {
hs.current.decompress = wrapped
}
}
}
type hooks struct {
marshal Marshaller
unmarshall Unmarshaller
compress CompressionHook
decompress CompressionHook
}
func (h *hooks) setDefaults() {
if h.marshal == nil {
h.marshal = func(v any) ([]byte, error) {
return nil, nil
}
}
if h.unmarshall == nil {
h.unmarshall = func(b []byte, v any) error {
return nil
}
}
if h.compress == nil {
h.compress = func(data []byte) ([]byte, error) {
return nil, nil
}
}
if h.decompress == nil {
h.decompress = func(data []byte) ([]byte, error) {
return nil, nil
}
}
}