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  }