forked from cloudfoundry/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
map.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
}
type ConcreteMap map[interface{}]interface{}
func newEmptyMap() Map {
return &ConcreteMap{}
}
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")
}
func (data *ConcreteMap) IsEmpty() bool {
return data.Count() == 0
}
func (data *ConcreteMap) Count() int {
return len(*data)
}
func (data *ConcreteMap) Has(key interface{}) bool {
_, ok := (*data)[key]
return ok
}
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) IsNil(key interface{}) bool {
maybe, ok := (*data)[key]
return ok && maybe == nil
}
func (data *ConcreteMap) NotNil(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) Get(key interface{}) interface{} {
return (*data)[key]
}
func (data *ConcreteMap) Set(key, value interface{}) {
(*data)[key] = value
}
func (data *ConcreteMap) Delete(key interface{}) {
delete(*data, key)
}
func (data *ConcreteMap) String() string {
return fmt.Sprintf("% v", *data)
}
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
}
}
type Iterator func(key, val interface{})
func Each(collection Map, cb Iterator) {
for _, key := range collection.Keys() {
cb(key, collection.Get(key))
}
}
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")
}