-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeys.go
168 lines (147 loc) · 3.6 KB
/
keys.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Package keys offers a small helper for managing
// multiple set of keys / values of the type string string
// It allows for keys to be searched from multiple source
package keys
import "sync"
// Getter retrieves the value of the variable named by the key.
// It returns the value, which will be empty if the variable is not present.
// To distinguish between an empty value and an unset value, use Lookup.
type Getter interface {
Get(k string) string
}
// Lookuper retrieves the value of the variable named by the key.
// If the variable is present in the environment the value (which may be empty)
// is returned and the boolean is true. Otherwise the returned value will be empty
// and the boolean will be false.
type Lookuper interface {
Lookup(k string) (string, bool)
}
// Setter sets the value of the variable named by the key.
// It returns an error, if any.
type Setter interface {
Set(k, v string) error
}
// Manager is the inter interface to a key manager
type Manager interface {
Getter
Lookuper
Setter
}
// KeyManager is a basic implementation in memory
// of a Manager
type KeyManager struct {
localData map[string]string
lock sync.RWMutex
}
// Lookup see interface definition
func (km *KeyManager) Lookup(key string) (string, bool) {
km.lock.RLock()
defer km.lock.RUnlock()
k, v := km.localData[key]
return k, v
}
// Get see interface definition
func (km *KeyManager) Get(key string) string {
km.lock.RLock()
defer km.lock.RUnlock()
k, _ := km.Lookup(key)
return k
}
// Set see interface definition
func (km *KeyManager) Set(key, value string) error {
km.lock.Lock()
defer km.lock.Unlock()
km.localData[key] = value
return nil
}
// NewKeyManager gives a basic key manager that will
// store values in memory
func NewKeyManager() Manager {
return &KeyManager{
localData: make(map[string]string),
}
}
type cbGet struct {
mgr []Getter
}
func (km *cbGet) Get(key string) string {
for _, keym := range km.mgr {
if k := keym.Get(key); k != "" {
return k
}
}
return ""
}
type cbLook struct {
mgr []Lookuper
lock sync.RWMutex
}
func (km *cbLook) Lookup(key string) (string, bool) {
km.lock.RLock()
defer km.lock.RUnlock()
for _, keym := range km.mgr {
if k, ok := keym.Lookup(key); ok {
return k, ok
}
}
return "", false
}
type combinedManager struct {
localData map[string]string
mgr []Manager
lock sync.RWMutex
}
func (km *combinedManager) Get(key string) string {
km.lock.RLock()
defer km.lock.RUnlock()
k, _ := km.Lookup(key)
return k
}
func (km *combinedManager) Lookup(key string) (string, bool) {
km.lock.RLock()
defer km.lock.RUnlock()
if k, ok := km.localData[key]; ok {
return k, ok
}
for _, keym := range km.mgr {
if k, ok := keym.Lookup(key); ok {
return k, ok
}
}
return "", false
}
func (km *combinedManager) Set(k, v string) error {
km.lock.Lock()
defer km.lock.Unlock()
km.localData[k] = v
return nil
}
// MultiGetter takes multiple lookups and combines them to find
// the value of the first one that is not a blank string
func MultiGetter(km ...Getter) Getter {
res := &cbGet{}
for _, k := range km {
res.mgr = append(res.mgr, k)
}
return res
}
// MultiLookuper takes multiple lookups and combines them to find
// the value of any
func MultiLookuper(km ...Lookuper) Lookuper {
res := &cbLook{}
for _, k := range km {
res.mgr = append(res.mgr, k)
}
return res
}
// MultiManager takes multiple managers and combines them to find
// the value of any
func MultiManager(km ...Manager) Manager {
res := &combinedManager{
localData: make(map[string]string),
}
for _, k := range km {
res.mgr = append(res.mgr, k)
}
return res
}