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  }