github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/util/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 nil:
    37  		return newEmptyMap()
    38  	case Map:
    39  		return data
    40  	case map[string]string:
    41  		stringMap := newEmptyMap()
    42  		for key, val := range data {
    43  			stringMap.Set(key, val)
    44  		}
    45  		return stringMap
    46  	case map[string]interface{}:
    47  		stringToInterfaceMap := newEmptyMap()
    48  		for key, val := range data {
    49  			stringToInterfaceMap.Set(key, val)
    50  		}
    51  		return stringToInterfaceMap
    52  	case map[interface{}]interface{}:
    53  		mapp := ConcreteMap(data)
    54  		return &mapp
    55  	}
    56  
    57  	fmt.Printf("\n\n map: %T", data)
    58  	panic("NewMap called with unexpected argument")
    59  }
    60  
    61  func (data *ConcreteMap) IsEmpty() bool {
    62  	return data.Count() == 0
    63  }
    64  
    65  func (data *ConcreteMap) Count() int {
    66  	return len(*data)
    67  }
    68  
    69  func (data *ConcreteMap) Has(key interface{}) bool {
    70  	_, ok := (*data)[key]
    71  	return ok
    72  }
    73  
    74  func (data *ConcreteMap) Except(keys []interface{}) Map {
    75  	otherMap := NewMap()
    76  	Each(data, func(key, value interface{}) {
    77  		if !Contains(keys, key) {
    78  			otherMap.Set(key, value)
    79  		}
    80  	})
    81  	return otherMap
    82  }
    83  
    84  func (data *ConcreteMap) IsNil(key interface{}) bool {
    85  	maybe, ok := (*data)[key]
    86  	return ok && maybe == nil
    87  }
    88  
    89  func (data *ConcreteMap) NotNil(key interface{}) bool {
    90  	maybe, ok := (*data)[key]
    91  	return ok && maybe != nil
    92  }
    93  
    94  func (data *ConcreteMap) Keys() (keys []interface{}) {
    95  	keys = make([]interface{}, 0, data.Count())
    96  	for key := range *data {
    97  		keys = append(keys, key)
    98  	}
    99  
   100  	return
   101  }
   102  
   103  func (data *ConcreteMap) Get(key interface{}) interface{} {
   104  	return (*data)[key]
   105  }
   106  
   107  func (data *ConcreteMap) Set(key, value interface{}) {
   108  	(*data)[key] = value
   109  }
   110  
   111  func (data *ConcreteMap) Delete(key interface{}) {
   112  	delete(*data, key)
   113  }
   114  
   115  func (data *ConcreteMap) String() string {
   116  	return fmt.Sprintf("% v", *data)
   117  }
   118  
   119  func IsMappable(value interface{}) bool {
   120  	if value == nil {
   121  		return false
   122  	}
   123  	switch value.(type) {
   124  	case Map:
   125  		return true
   126  	default:
   127  		return reflect.TypeOf(value).Kind() == reflect.Map
   128  	}
   129  }
   130  
   131  type Iterator func(key, val interface{})
   132  
   133  func Each(collection Map, cb Iterator) {
   134  	for _, key := range collection.Keys() {
   135  		cb(key, collection.Get(key))
   136  	}
   137  }
   138  
   139  func Contains(collection, item interface{}) bool {
   140  	switch collection := collection.(type) {
   141  	case Map:
   142  		return collection.Has(item)
   143  	case []interface{}:
   144  		for _, val := range collection {
   145  			if val == item {
   146  				return true
   147  			}
   148  		}
   149  		return false
   150  	}
   151  
   152  	panic("unexpected type passed to Contains")
   153  }