/
Option.go
69 lines (54 loc) · 1.45 KB
/
Option.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
package fixtures
import (
"reflect"
"regexp"
)
type Option interface{ setup(c *config) }
type optionFunc func(c *config)
func (fn optionFunc) setup(c *config) { fn(c) }
func newConfig(opts ...Option) *config {
var c config
for _, opt := range opts {
opt.setup(&c)
}
return &c
}
type config struct {
skipByTags map[string][]string // tag -> values
}
func (c *config) GetSkipTags() map[string][]string {
if c.skipByTags == nil {
c.skipByTags = make(map[string][]string)
}
return c.skipByTags
}
var structFieldTagSeparator = regexp.MustCompile(`,|;`)
func (c *config) CanPopulateStructField(sf reflect.StructField) bool {
for tagName, values := range c.GetSkipTags() {
tag, ok := sf.Tag.Lookup(tagName)
if !ok {
continue
}
if len(values) == 0 {
return false
}
tagValueIndex := make(map[string]struct{})
for _, v := range structFieldTagSeparator.Split(tag, -1) {
tagValueIndex[v] = struct{}{}
}
for _, value := range values {
if _, ok := tagValueIndex[value]; ok {
return false
}
}
}
return true
}
// SkipByTag is an Option to skip a certain tag during the New function value population.
// If value is not provided, all matching tag will be skipped.
// If value or multiple value is provided, then matching tag only skipped if it matches the values.
func SkipByTag(tag string, values ...string) Option {
return optionFunc(func(c *config) {
c.GetSkipTags()[tag] = append(c.GetSkipTags()[tag], values...)
})
}