github.com/asifdxtreme/cli@v6.1.3-0.20150123051144-9ead8700b4ae+incompatible/generic/map.go (about) 1 package generic 2 3 import "fmt" 4 5 // interface declaration 6 type Map interface { 7 IsEmpty() bool 8 Count() int 9 Keys() []interface{} 10 Has(key interface{}) bool 11 Except(keys []interface{}) Map 12 IsNil(key interface{}) bool 13 NotNil(key interface{}) bool 14 Get(key interface{}) interface{} 15 Set(key interface{}, value interface{}) 16 Delete(key interface{}) 17 String() string 18 } 19 20 // concrete map type 21 type ConcreteMap map[interface{}]interface{} 22 23 // constructors 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 // implementing interface methods 60 func (data *ConcreteMap) IsEmpty() bool { 61 return data.Count() == 0 62 } 63 64 func (data *ConcreteMap) Count() int { 65 return len(*data) 66 } 67 68 func (data *ConcreteMap) Has(key interface{}) bool { 69 _, ok := (*data)[key] 70 return ok 71 } 72 73 func (data *ConcreteMap) Except(keys []interface{}) Map { 74 otherMap := NewMap() 75 Each(data, func(key, value interface{}) { 76 if !Contains(keys, key) { 77 otherMap.Set(key, value) 78 } 79 }) 80 return otherMap 81 } 82 83 func (data *ConcreteMap) IsNil(key interface{}) bool { 84 maybe, ok := (*data)[key] 85 return ok && maybe == nil 86 } 87 88 func (data *ConcreteMap) NotNil(key interface{}) bool { 89 maybe, ok := (*data)[key] 90 return ok && maybe != nil 91 } 92 93 func (data *ConcreteMap) Keys() (keys []interface{}) { 94 keys = make([]interface{}, 0, data.Count()) 95 for key := range *data { 96 keys = append(keys, key) 97 } 98 99 return 100 } 101 102 func (data *ConcreteMap) Get(key interface{}) interface{} { 103 return (*data)[key] 104 } 105 106 func (data *ConcreteMap) Set(key, value interface{}) { 107 (*data)[key] = value 108 } 109 110 func (data *ConcreteMap) Delete(key interface{}) { 111 delete(*data, key) 112 } 113 114 func (data *ConcreteMap) String() string { 115 return fmt.Sprintf("% v", *data) 116 } 117 118 // helper functions 119 func IsMappable(value interface{}) bool { 120 switch value.(type) { 121 case Map: 122 return true 123 case map[string]interface{}: 124 return true 125 case map[interface{}]interface{}: 126 return true 127 default: 128 return false 129 } 130 } 131 132 type Iterator func(key, val interface{}) 133 134 func Each(collection Map, cb Iterator) { 135 for _, key := range collection.Keys() { 136 cb(key, collection.Get(key)) 137 } 138 } 139 140 func Contains(collection, item interface{}) bool { 141 switch collection := collection.(type) { 142 case Map: 143 return collection.Has(item) 144 case []interface{}: 145 for _, val := range collection { 146 if val == item { 147 return true 148 } 149 } 150 return false 151 } 152 153 panic("unexpected type passed to Contains") 154 }