forked from cloudfoundry/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmap.go
153 lines (129 loc) · 2.92 KB
/
map.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
package generic
import (
"fmt"
"reflect"
)
type Map interface {
IsEmpty() bool
Count() int
Keys() []interface{}
Has(key interface{}) bool
Except(keys []interface{}) Map
IsNil(key interface{}) bool
NotNil(key interface{}) bool
Get(key interface{}) interface{}
Set(key interface{}, value interface{})
Delete(key interface{})
String() string
}
func NewMap(data ...interface{}) Map {
if len(data) == 0 {
return newEmptyMap()
} else if len(data) > 1 {
panic("NewMap called with more than one argument")
}
switch data := data[0].(type) {
case nil:
return newEmptyMap()
case Map:
return data
case map[string]string:
stringMap := newEmptyMap()
for key, val := range data {
stringMap.Set(key, val)
}
return stringMap
case map[string]interface{}:
stringToInterfaceMap := newEmptyMap()
for key, val := range data {
stringToInterfaceMap.Set(key, val)
}
return stringToInterfaceMap
case map[interface{}]interface{}:
mapp := ConcreteMap(data)
return &mapp
}
fmt.Printf("\n\n map: %T", data)
panic("NewMap called with unexpected argument")
}
type Iterator func(key, val interface{})
func newEmptyMap() Map {
return &ConcreteMap{}
}
type ConcreteMap map[interface{}]interface{}
func (data *ConcreteMap) Count() int {
return len(*data)
}
func (data *ConcreteMap) Delete(key interface{}) {
delete(*data, key)
}
func (data *ConcreteMap) Except(keys []interface{}) Map {
otherMap := NewMap()
Each(data, func(key, value interface{}) {
if !Contains(keys, key) {
otherMap.Set(key, value)
}
})
return otherMap
}
func (data *ConcreteMap) Get(key interface{}) interface{} {
return (*data)[key]
}
func (data *ConcreteMap) Has(key interface{}) bool {
_, ok := (*data)[key]
return ok
}
func (data *ConcreteMap) IsEmpty() bool {
return data.Count() == 0
}
func (data *ConcreteMap) IsNil(key interface{}) bool {
maybe, ok := (*data)[key]
return ok && maybe == nil
}
func (data *ConcreteMap) Keys() (keys []interface{}) {
keys = make([]interface{}, 0, data.Count())
for key := range *data {
keys = append(keys, key)
}
return
}
func (data *ConcreteMap) NotNil(key interface{}) bool {
maybe, ok := (*data)[key]
return ok && maybe != nil
}
func (data *ConcreteMap) Set(key, value interface{}) {
(*data)[key] = value
}
func (data *ConcreteMap) String() string {
return fmt.Sprintf("% v", *data)
}
func Contains(collection, item interface{}) bool {
switch collection := collection.(type) {
case Map:
return collection.Has(item)
case []interface{}:
for _, val := range collection {
if val == item {
return true
}
}
return false
}
panic("unexpected type passed to Contains")
}
func Each(collection Map, cb Iterator) {
for _, key := range collection.Keys() {
cb(key, collection.Get(key))
}
}
func IsMappable(value interface{}) bool {
if value == nil {
return false
}
switch value.(type) {
case Map:
return true
default:
return reflect.TypeOf(value).Kind() == reflect.Map
}
}