forked from infobloxopen/atlas-app-toolkit
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mapper.go
148 lines (125 loc) · 3.78 KB
/
mapper.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package errors
import (
"context"
"regexp"
"strings"
)
// Mapper struct ...
type Mapper struct {
mapFuncs []MapFunc
}
// Map function performs a mapping from error given following a chain of
// mappings that were defined prior to the Map call.
func (m *Mapper) Map(ctx context.Context, err error) error {
for _, mapFunc := range m.mapFuncs {
if resErr, ok := mapFunc(ctx, err); ok {
return resErr
}
}
return InitContainer()
}
// AddMapping function appends a list of mapping functions to a mapping chain.
func (m *Mapper) AddMapping(mf ...MapFunc) *Mapper {
if m.mapFuncs == nil {
m.mapFuncs = []MapFunc{}
}
m.mapFuncs = append(m.mapFuncs, mf...)
return m
}
// MapCond function takes an error and returns flag that indicates whether the
// map condition was met.
type MapCond func(error) bool
// Error function ...
func (mc MapCond) Error() string { return "MapCond" }
// MapFunc function takes an error and returns mapped error and flag that
// indicates whether the mapping was performed successfully.
type MapFunc func(context.Context, error) (error, bool)
// Error function ...
func (mc MapFunc) Error() string { return "MapFunc" }
// NewMapping function creates a mapping function based on error interfaces
// passed to it. src can be either MapCond and dst can be MapFunc.
func NewMapping(src error, dst error) MapFunc {
var mapCond MapCond
var mapFunc MapFunc
if v, ok := src.(MapCond); ok {
mapCond = v
} else {
mapCond = CondEq(src.Error())
}
if v, ok := dst.(MapFunc); ok {
mapFunc = v
} else {
mapFunc = func(ctx context.Context, err error) (error, bool) {
return dst, true
}
}
return func(ctx context.Context, err error) (error, bool) {
if mapCond(err) {
return mapFunc(ctx, err)
}
return nil, false
}
}
// * -------------------------------------------- *
// * Various helper condition building functions. *
// * -------------------------------------------- *
// CondEq function takes a string as an input and returns a condition function
// that checks whether the error is equal to a string given.
func CondEq(src string) MapCond {
return func(err error) bool {
return src == err.Error()
}
}
// CondReMatch function takes a string regexp pattern as an input and returns a
// condition function that checks whether the error matches the pattern given.
func CondReMatch(pattern string) MapCond {
return func(err error) bool {
matched, _ := regexp.MatchString(pattern, err.Error())
return matched
}
}
// CondHasSuffix function takes a string as an input and returns a condition
// function that checks whether the error ends with the string given.
func CondHasSuffix(suffix string) MapCond {
return func(err error) bool {
return strings.HasSuffix(err.Error(), suffix)
}
}
// CondHasPrefix function takes a string as an input and returns a condition
// function that checks whether the error starts with the string given.
func CondHasPrefix(prefix string) MapCond {
return func(err error) bool {
return strings.HasPrefix(err.Error(), prefix)
}
}
// CondNot function takes a condtion function as an input and returns a
// function that asserts inverse result.
func CondNot(mc MapCond) MapCond {
return func(err error) bool {
return !mc(err)
}
}
// CondAnd function takes a list of condition function as an input and returns
// a function that asserts true if and only if all conditions are satisfied.
func CondAnd(mcs ...MapCond) MapCond {
return func(err error) bool {
for _, v := range mcs {
if !v(err) {
return false
}
}
return true
}
}
// CondOr function takes a list of condition function as an input and returns
// a function that asserts true if at least one of conditions is satisfied.
func CondOr(mcs ...MapCond) MapCond {
return func(err error) bool {
for _, v := range mcs {
if v(err) {
return true
}
}
return false
}
}