-
Notifications
You must be signed in to change notification settings - Fork 2
/
fillers.go
148 lines (136 loc) · 3.04 KB
/
fillers.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 nfigure
import (
"github.com/AlekSi/pointer"
"github.com/muir/reflectutils"
)
type fillerCollection struct {
m map[string]Filler
order []string
dirty bool
}
// Copy makes shallow copy.
func (f fillerCollection) Copy() *fillerCollection {
n := fillerCollection{
m: make(map[string]Filler),
order: make([]string, len(f.m)),
}
for tag, filler := range f.m {
n.m[tag] = filler
}
f.Clean()
copy(n.order, f.order)
debug("fillers: copy, order now", n.order, f)
return &n
}
func newFillerCollection() *fillerCollection {
debug("fillers: new", callers(3))
return &fillerCollection{
m: make(map[string]Filler),
}
}
func (f *fillerCollection) IsEmpty() bool {
if f == nil {
return true
}
return len(f.m) == 0
}
func (f *fillerCollection) Order() []string {
f.Clean()
debug("fillers: order:", f.order)
return f.order
}
func (f *fillerCollection) Remove(tag string) {
if _, ok := f.m[tag]; ok {
debug("fillers: REMOVE", tag)
f.dirty = true
delete(f.m, tag)
}
}
func (f *fillerCollection) Add(tag string, filler Filler) {
if filler == nil {
f.Remove(tag)
} else {
if _, ok := f.m[tag]; !ok {
f.order = append(f.order, tag)
debug("fillers: ADD", tag, "order now", f.order)
}
f.m[tag] = filler
}
}
// Build modifies the fillerCollection it receives and returns it
func (f *fillerCollection) Build(tag string, filler Filler) *fillerCollection {
f.Add(tag, filler)
return f
}
func (f *fillerCollection) Clean() {
if !f.dirty {
debug("fillers: Clean, not dirty")
return
}
f.dirty = false
for i, tag := range f.order {
if _, ok := f.m[tag]; ok {
continue
}
n := make([]string, i, len(f.m))
if i > 0 {
copy(n, f.order[:i])
}
for _, tag := range f.order[i+1:] {
if _, ok := f.m[tag]; ok {
n = append(n, tag)
}
}
f.order = n
break
}
debug("fillers: after clean, order is", f.order)
}
type fillPair struct {
ForcedTag string // because Tag.Tag may be empty
Tag reflectutils.Tag
Filler Filler
}
func (f *fillerCollection) pairs(tagSet reflectutils.TagSet, meta metaFields) []fillPair {
debug("fillers: creating pairs", tagSet, "order (for backup) is", f.Order())
pairs := make([]fillPair, 0, len(f.m))
done := make(map[string]struct{})
p := func(tag reflectutils.Tag) {
if filler, ok := f.m[tag.Tag]; ok {
debug("fillers: creating pairs, found filler for tag", tag.Tag)
pairs = append(pairs, fillPair{
Filler: filler,
Tag: tag,
ForcedTag: tag.Tag,
})
done[tag.Tag] = struct{}{}
} else {
debug("fillers, no filler (no pair) for", tag.Tag)
}
}
if pointer.GetBool(meta.First) {
for _, tag := range tagSet.Tags {
p(tag)
}
} else {
for i := len(tagSet.Tags) - 1; i >= 0; i-- {
p(tagSet.Tags[i])
}
}
for _, tag := range f.Order() {
if _, ok := done[tag]; ok {
continue
}
filler, ok := f.m[tag]
if !ok {
debug("fillers: creating pairs, could not find", tag)
continue
}
debug("fillers: creating pairs, found backup", tag)
pairs = append(pairs, fillPair{
Filler: filler,
ForcedTag: tag,
})
}
return pairs
}