github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/utils/generic/map.go (about) 1 package generic 2 3 import ( 4 "fmt" 5 "reflect" 6 ) 7 8 type Map interface { 9 IsEmpty() bool 10 Count() int 11 Keys() []interface{} 12 Has(key interface{}) bool 13 Except(keys []interface{}) Map 14 IsNil(key interface{}) bool 15 NotNil(key interface{}) bool 16 Get(key interface{}) interface{} 17 Set(key interface{}, value interface{}) 18 Delete(key interface{}) 19 String() string 20 } 21 22 type ConcreteMap map[interface{}]interface{} 23 24 func newEmptyMap() Map { 25 return &ConcreteMap{} 26 } 27 28 func NewMap(data ...interface{}) Map { 29 if len(data) == 0 { 30 return newEmptyMap() 31 } else if len(data) > 1 { 32 panic("NewMap called with more than one argument") 33 } 34 35 switch data := data[0].(type) { 36 case Map: 37 return data 38 case map[string]string: 39 stringMap := newEmptyMap() 40 for key, val := range data { 41 stringMap.Set(key, val) 42 } 43 return stringMap 44 case map[string]interface{}: 45 stringToInterfaceMap := newEmptyMap() 46 for key, val := range data { 47 stringToInterfaceMap.Set(key, val) 48 } 49 return stringToInterfaceMap 50 case map[interface{}]interface{}: 51 mapp := ConcreteMap(data) 52 return &mapp 53 } 54 55 fmt.Printf("\n\n map: %T", data) 56 panic("NewMap called with unexpected argument") 57 } 58 59 func (data *ConcreteMap) IsEmpty() bool { 60 return data.Count() == 0 61 } 62 63 func (data *ConcreteMap) Count() int { 64 return len(*data) 65 } 66 67 func (data *ConcreteMap) Has(key interface{}) bool { 68 _, ok := (*data)[key] 69 return ok 70 } 71 72 func (data *ConcreteMap) Except(keys []interface{}) Map { 73 otherMap := NewMap() 74 Each(data, func(key, value interface{}) { 75 if !Contains(keys, key) { 76 otherMap.Set(key, value) 77 } 78 }) 79 return otherMap 80 } 81 82 func (data *ConcreteMap) IsNil(key interface{}) bool { 83 maybe, ok := (*data)[key] 84 return ok && maybe == nil 85 } 86 87 func (data *ConcreteMap) NotNil(key interface{}) bool { 88 maybe, ok := (*data)[key] 89 return ok && maybe != nil 90 } 91 92 func (data *ConcreteMap) Keys() (keys []interface{}) { 93 keys = make([]interface{}, 0, data.Count()) 94 for key := range *data { 95 keys = append(keys, key) 96 } 97 98 return 99 } 100 101 func (data *ConcreteMap) Get(key interface{}) interface{} { 102 return (*data)[key] 103 } 104 105 func (data *ConcreteMap) Set(key, value interface{}) { 106 (*data)[key] = value 107 } 108 109 func (data *ConcreteMap) Delete(key interface{}) { 110 delete(*data, key) 111 } 112 113 func (data *ConcreteMap) String() string { 114 return fmt.Sprintf("% v", *data) 115 } 116 117 func IsMappable(value interface{}) bool { 118 switch value.(type) { 119 case Map: 120 return true 121 default: 122 return reflect.TypeOf(value).Kind() == reflect.Map 123 } 124 } 125 126 type Iterator func(key, val interface{}) 127 128 func Each(collection Map, cb Iterator) { 129 for _, key := range collection.Keys() { 130 cb(key, collection.Get(key)) 131 } 132 } 133 134 func Contains(collection, item interface{}) bool { 135 switch collection := collection.(type) { 136 case Map: 137 return collection.Has(item) 138 case []interface{}: 139 for _, val := range collection { 140 if val == item { 141 return true 142 } 143 } 144 return false 145 } 146 147 panic("unexpected type passed to Contains") 148 }