github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/key/key.go (about)

     1  // Copyright (c) 2015 Arista Networks, Inc.
     2  // Use of this source code is governed by the Apache License 2.0
     3  // that can be found in the COPYING file.
     4  
     5  package key
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/base64"
    10  	"encoding/json"
    11  	"fmt"
    12  	"math"
    13  	"strconv"
    14  
    15  	"github.com/aristanetworks/goarista/value"
    16  )
    17  
    18  // Key represents the Key in the updates and deletes of the Notification
    19  // objects.  The only reason this exists is that Go won't let us define
    20  // our own hash function for non-hashable types, and unfortunately we
    21  // need to be able to index maps by map[string]interface{} objects
    22  // and slices by []interface{} objects.
    23  type Key interface {
    24  	Key() interface{}
    25  	String() string
    26  	Equal(other interface{}) bool
    27  }
    28  
    29  type mapKey map[string]interface{}
    30  
    31  type sliceKey []interface{}
    32  
    33  type interfaceKey struct {
    34  	key interface{}
    35  }
    36  
    37  type strKey string
    38  type bytesKey string
    39  
    40  type int8Key int8
    41  type int16Key int16
    42  type int32Key int32
    43  type int64Key int64
    44  
    45  type uint8Key uint8
    46  type uint16Key uint16
    47  type uint32Key uint32
    48  type uint64Key uint64
    49  
    50  type float32Key float32
    51  type float64Key float64
    52  
    53  type boolKey bool
    54  
    55  type pointerKey struct {
    56  	sliceKey
    57  }
    58  
    59  type pathKey struct {
    60  	sliceKey
    61  }
    62  
    63  type nilKey struct{}
    64  
    65  func pathToSlice(path Path) []interface{} {
    66  	s := make([]interface{}, len(path))
    67  	for i, element := range path {
    68  		s[i] = element.Key()
    69  	}
    70  	return s
    71  }
    72  
    73  func sliceToPath(s []interface{}) Path {
    74  	path := make(Path, len(s))
    75  	for i, intf := range s {
    76  		path[i] = New(intf)
    77  	}
    78  	return path
    79  }
    80  
    81  func pointerToSlice(ptr Pointer) []interface{} {
    82  	return pathToSlice(ptr.Pointer())
    83  }
    84  
    85  func sliceToPointer(s []interface{}) pointer {
    86  	return pointer(sliceToPath(s))
    87  }
    88  
    89  // New wraps the given value in a Key.
    90  // This function panics if the value passed in isn't allowed in a Key or
    91  // doesn't implement value.Value.
    92  func New(intf interface{}) Key {
    93  	switch t := intf.(type) {
    94  	case nil:
    95  		return nilKey{}
    96  	case map[string]interface{}:
    97  		return mapKey(t)
    98  	case []interface{}:
    99  		return sliceKey(t)
   100  	case string:
   101  		return strKey(t)
   102  	case int8:
   103  		return int8Key(t)
   104  	case int16:
   105  		return int16Key(t)
   106  	case int32:
   107  		return int32Key(t)
   108  	case int64:
   109  		return int64Key(t)
   110  	case uint8:
   111  		return uint8Key(t)
   112  	case uint16:
   113  		return uint16Key(t)
   114  	case uint32:
   115  		return uint32Key(t)
   116  	case uint64:
   117  		return uint64Key(t)
   118  	case float32:
   119  		return float32Key(t)
   120  	case float64:
   121  		return float64Key(t)
   122  	case bool:
   123  		return boolKey(t)
   124  	case value.Value:
   125  		return interfaceKey{key: intf}
   126  	case Pointer:
   127  		return pointerKey{sliceKey(pointerToSlice(t))}
   128  	case []byte:
   129  		return bytesKey(t)
   130  	case Path:
   131  		return pathKey{sliceKey(pathToSlice(t))}
   132  	default:
   133  		panic(fmt.Sprintf("Invalid type for key: %T", intf))
   134  	}
   135  }
   136  
   137  func (k interfaceKey) Key() interface{} {
   138  	return k.key
   139  }
   140  
   141  func (k interfaceKey) String() string {
   142  	return stringify(k.key)
   143  }
   144  
   145  func (k interfaceKey) GoString() string {
   146  	return fmt.Sprintf("key.New(%#v)", k.Key())
   147  }
   148  
   149  func (k interfaceKey) MarshalJSON() ([]byte, error) {
   150  	return json.Marshal(k.Key())
   151  }
   152  
   153  func (k interfaceKey) Equal(other interface{}) bool {
   154  	o, ok := other.(Key)
   155  	return ok && keyEqual(k.key, o.Key())
   156  }
   157  
   158  func (k interfaceKey) Hash() uint64 {
   159  	if h, ok := k.key.(Hashable); ok {
   160  		return h.Hash()
   161  	}
   162  	return uint64(_nilinterhash(k.key))
   163  }
   164  
   165  // Comparable types have an equality-testing method.
   166  type Comparable interface {
   167  	// Equal returns true if this object is equal to the other one.
   168  	Equal(other interface{}) bool
   169  }
   170  
   171  func mapStringEqual(a, b map[string]interface{}) bool {
   172  	if len(a) != len(b) {
   173  		return false
   174  	}
   175  	for k, av := range a {
   176  		if bv, ok := b[k]; !ok || !keyEqual(av, bv) {
   177  			return false
   178  		}
   179  	}
   180  	return true
   181  }
   182  
   183  func sliceEqual(a, b []interface{}) bool {
   184  	if len(a) != len(b) {
   185  		return false
   186  	}
   187  	for i, v := range a {
   188  		if !keyEqual(v, b[i]) {
   189  			return false
   190  		}
   191  	}
   192  	return true
   193  }
   194  
   195  // Equal compares two arbitrary interfaces for equality.
   196  func Equal(a, b interface{}) bool {
   197  	return keyEqual(a, b)
   198  }
   199  
   200  func keyEqual(a, b interface{}) bool {
   201  	switch a := a.(type) {
   202  	case map[string]interface{}:
   203  		b, ok := b.(map[string]interface{})
   204  		return ok && mapStringEqual(a, b)
   205  	case []interface{}:
   206  		b, ok := b.([]interface{})
   207  		return ok && sliceEqual(a, b)
   208  	case []byte:
   209  		b, ok := b.([]byte)
   210  		return ok && bytes.Equal(a, b)
   211  	case Comparable:
   212  		return a.Equal(b)
   213  	case Pointer:
   214  		b, ok := b.(Pointer)
   215  		return ok && pointerEqual(a, b)
   216  	case Path:
   217  		b, ok := b.(Path)
   218  		return ok && pathEqual(a, b)
   219  	}
   220  
   221  	return a == b
   222  }
   223  
   224  func (k mapKey) Key() interface{} {
   225  	return map[string]interface{}(k)
   226  }
   227  
   228  func (k mapKey) String() string {
   229  	return stringify(k.Key())
   230  }
   231  
   232  func (k mapKey) GoString() string {
   233  	return fmt.Sprintf("key.New(%#v)", k.Key())
   234  }
   235  
   236  func (k mapKey) MarshalJSON() ([]byte, error) {
   237  	return json.Marshal(k.Key())
   238  }
   239  
   240  func (k mapKey) Equal(other interface{}) bool {
   241  	o, ok := other.(mapKey)
   242  	return ok && mapStringEqual(k, o)
   243  }
   244  
   245  func (k mapKey) Hash() uint64 {
   246  	if k == nil {
   247  		return 0
   248  	}
   249  	return uint64(hashMapString(k))
   250  }
   251  
   252  func (k sliceKey) Key() interface{} {
   253  	return []interface{}(k)
   254  }
   255  
   256  func (k sliceKey) String() string {
   257  	return stringify(k.Key())
   258  }
   259  
   260  func (k sliceKey) GoString() string {
   261  	return fmt.Sprintf("key.New(%#v)", k.Key())
   262  }
   263  
   264  func (k sliceKey) MarshalJSON() ([]byte, error) {
   265  	return json.Marshal(k.Key())
   266  }
   267  
   268  func (k sliceKey) Equal(other interface{}) bool {
   269  	o, ok := other.(sliceKey)
   270  	return ok && sliceEqual(k, o)
   271  }
   272  
   273  func (k sliceKey) Hash() uint64 {
   274  	if k == nil {
   275  		return 0
   276  	}
   277  	return uint64(hashSlice(k))
   278  }
   279  
   280  func (k strKey) Key() interface{} {
   281  	return string(k)
   282  }
   283  
   284  func (k strKey) String() string {
   285  	return string(k)
   286  }
   287  
   288  func (k strKey) GoString() string {
   289  	return fmt.Sprintf("key.New(%q)", string(k))
   290  }
   291  
   292  func (k strKey) KeyString() string {
   293  	return escape(string(k))
   294  }
   295  
   296  func (k strKey) MarshalJSON() ([]byte, error) {
   297  	return json.Marshal(escape(string(k)))
   298  }
   299  
   300  func (k strKey) Equal(other interface{}) bool {
   301  	o, ok := other.(strKey)
   302  	return ok && k == o
   303  }
   304  
   305  // Key interface implementation for []bytes
   306  func (k bytesKey) Key() interface{} {
   307  	return string(k)
   308  }
   309  
   310  func (k bytesKey) String() string {
   311  	return base64.StdEncoding.EncodeToString([]byte(k))
   312  }
   313  
   314  func (k bytesKey) GoString() string {
   315  	return fmt.Sprintf("key.New(%q)", []byte(k))
   316  }
   317  
   318  func (k bytesKey) MarshalJSON() ([]byte, error) {
   319  	return json.Marshal([]byte(k))
   320  }
   321  
   322  func (k bytesKey) Equal(other interface{}) bool {
   323  	o, ok := other.(bytesKey)
   324  	return ok && o == k
   325  }
   326  
   327  // Key interface implementation for int8
   328  func (k int8Key) Key() interface{} {
   329  	return int8(k)
   330  }
   331  
   332  func (k int8Key) String() string {
   333  	return strconv.FormatInt(int64(k), 10)
   334  }
   335  
   336  func (k int8Key) GoString() string {
   337  	return fmt.Sprintf("key.New(int8(%d))", int8(k))
   338  }
   339  
   340  func (k int8Key) MarshalJSON() ([]byte, error) {
   341  	return []byte(strconv.FormatInt(int64(k), 10)), nil
   342  }
   343  
   344  func (k int8Key) Equal(other interface{}) bool {
   345  	o, ok := other.(int8Key)
   346  	return ok && k == o
   347  }
   348  
   349  // Key interface implementation for int16
   350  func (k int16Key) Key() interface{} {
   351  	return int16(k)
   352  }
   353  
   354  func (k int16Key) String() string {
   355  	return strconv.FormatInt(int64(k), 10)
   356  }
   357  
   358  func (k int16Key) GoString() string {
   359  	return fmt.Sprintf("key.New(int16(%d))", int16(k))
   360  }
   361  
   362  func (k int16Key) MarshalJSON() ([]byte, error) {
   363  	return []byte(strconv.FormatInt(int64(k), 10)), nil
   364  }
   365  
   366  func (k int16Key) Equal(other interface{}) bool {
   367  	o, ok := other.(int16Key)
   368  	return ok && k == o
   369  }
   370  
   371  // Key interface implementation for int32
   372  func (k int32Key) Key() interface{} {
   373  	return int32(k)
   374  }
   375  
   376  func (k int32Key) String() string {
   377  	return strconv.FormatInt(int64(k), 10)
   378  }
   379  
   380  func (k int32Key) GoString() string {
   381  	return fmt.Sprintf("key.New(int32(%d))", int32(k))
   382  }
   383  
   384  func (k int32Key) MarshalJSON() ([]byte, error) {
   385  	return []byte(strconv.FormatInt(int64(k), 10)), nil
   386  }
   387  
   388  func (k int32Key) Equal(other interface{}) bool {
   389  	o, ok := other.(int32Key)
   390  	return ok && k == o
   391  }
   392  
   393  // Key interface implementation for int64
   394  func (k int64Key) Key() interface{} {
   395  	return int64(k)
   396  }
   397  
   398  func (k int64Key) String() string {
   399  	return strconv.FormatInt(int64(k), 10)
   400  }
   401  
   402  func (k int64Key) GoString() string {
   403  	return fmt.Sprintf("key.New(int64(%d))", int64(k))
   404  }
   405  
   406  func (k int64Key) MarshalJSON() ([]byte, error) {
   407  	return []byte(strconv.FormatInt(int64(k), 10)), nil
   408  }
   409  
   410  func (k int64Key) Equal(other interface{}) bool {
   411  	o, ok := other.(int64Key)
   412  	return ok && k == o
   413  }
   414  
   415  // Key interface implementation for uint8
   416  func (k uint8Key) Key() interface{} {
   417  	return uint8(k)
   418  }
   419  
   420  func (k uint8Key) String() string {
   421  	return strconv.FormatUint(uint64(k), 10)
   422  }
   423  
   424  func (k uint8Key) GoString() string {
   425  	return fmt.Sprintf("key.New(uint8(%d))", uint8(k))
   426  }
   427  
   428  func (k uint8Key) MarshalJSON() ([]byte, error) {
   429  	return []byte(strconv.FormatUint(uint64(k), 10)), nil
   430  }
   431  
   432  func (k uint8Key) Equal(other interface{}) bool {
   433  	o, ok := other.(uint8Key)
   434  	return ok && k == o
   435  }
   436  
   437  // Key interface implementation for uint16
   438  func (k uint16Key) Key() interface{} {
   439  	return uint16(k)
   440  }
   441  
   442  func (k uint16Key) String() string {
   443  	return strconv.FormatUint(uint64(k), 10)
   444  }
   445  
   446  func (k uint16Key) GoString() string {
   447  	return fmt.Sprintf("key.New(uint16(%d))", uint16(k))
   448  }
   449  
   450  func (k uint16Key) MarshalJSON() ([]byte, error) {
   451  	return []byte(strconv.FormatUint(uint64(k), 10)), nil
   452  }
   453  
   454  func (k uint16Key) Equal(other interface{}) bool {
   455  	o, ok := other.(uint16Key)
   456  	return ok && k == o
   457  }
   458  
   459  // Key interface implementation for uint32
   460  func (k uint32Key) Key() interface{} {
   461  	return uint32(k)
   462  }
   463  
   464  func (k uint32Key) String() string {
   465  	return strconv.FormatUint(uint64(k), 10)
   466  }
   467  
   468  func (k uint32Key) GoString() string {
   469  	return fmt.Sprintf("key.New(uint32(%d))", uint32(k))
   470  }
   471  
   472  func (k uint32Key) MarshalJSON() ([]byte, error) {
   473  	return []byte(strconv.FormatUint(uint64(k), 10)), nil
   474  }
   475  
   476  func (k uint32Key) Equal(other interface{}) bool {
   477  	o, ok := other.(uint32Key)
   478  	return ok && k == o
   479  }
   480  
   481  // Key interface implementation for uint64
   482  func (k uint64Key) Key() interface{} {
   483  	return uint64(k)
   484  }
   485  
   486  func (k uint64Key) String() string {
   487  	return strconv.FormatUint(uint64(k), 10)
   488  }
   489  
   490  func (k uint64Key) GoString() string {
   491  	return fmt.Sprintf("key.New(uint64(%d))", uint64(k))
   492  }
   493  
   494  func (k uint64Key) MarshalJSON() ([]byte, error) {
   495  	return []byte(strconv.FormatUint(uint64(k), 10)), nil
   496  }
   497  
   498  func (k uint64Key) Equal(other interface{}) bool {
   499  	o, ok := other.(uint64Key)
   500  	return ok && k == o
   501  }
   502  
   503  // Key interface implementation for float32
   504  func (k float32Key) Key() interface{} {
   505  	return float32(k)
   506  }
   507  
   508  func (k float32Key) String() string {
   509  	return "f" + strconv.FormatInt(int64(math.Float32bits(float32(k))), 10)
   510  }
   511  
   512  func (k float32Key) GoString() string {
   513  	return fmt.Sprintf("key.New(float32(%v))", float32(k))
   514  }
   515  
   516  func (k float32Key) MarshalJSON() ([]byte, error) {
   517  	return []byte(strconv.FormatFloat(float64(k), 'g', -1, 32)), nil
   518  }
   519  
   520  func (k float32Key) Equal(other interface{}) bool {
   521  	o, ok := other.(float32Key)
   522  	return ok && k == o
   523  }
   524  
   525  // Key interface implementation for float64
   526  func (k float64Key) Key() interface{} {
   527  	return float64(k)
   528  }
   529  
   530  func (k float64Key) String() string {
   531  	return "f" + strconv.FormatInt(int64(math.Float64bits(float64(k))), 10)
   532  }
   533  
   534  func (k float64Key) GoString() string {
   535  	return fmt.Sprintf("key.New(float64(%v))", float64(k))
   536  }
   537  
   538  func (k float64Key) MarshalJSON() ([]byte, error) {
   539  	return []byte(strconv.FormatFloat(float64(k), 'g', -1, 64)), nil
   540  }
   541  
   542  func (k float64Key) Equal(other interface{}) bool {
   543  	o, ok := other.(float64Key)
   544  	return ok && k == o
   545  }
   546  
   547  // Key interface implementation for bool
   548  func (k boolKey) Key() interface{} {
   549  	return bool(k)
   550  }
   551  
   552  func (k boolKey) String() string {
   553  	return strconv.FormatBool(bool(k))
   554  }
   555  
   556  func (k boolKey) GoString() string {
   557  	return fmt.Sprintf("key.New(%v)", bool(k))
   558  }
   559  
   560  func (k boolKey) MarshalJSON() ([]byte, error) {
   561  	return []byte(strconv.FormatBool(bool(k))), nil
   562  }
   563  
   564  func (k boolKey) Equal(other interface{}) bool {
   565  	o, ok := other.(boolKey)
   566  	return ok && k == o
   567  }
   568  
   569  // Key interface implementation for Pointer
   570  func (k pointerKey) Key() interface{} {
   571  	return sliceToPointer(k.sliceKey)
   572  }
   573  
   574  func (k pointerKey) String() string {
   575  	return sliceToPointer(k.sliceKey).String()
   576  }
   577  
   578  func (k pointerKey) GoString() string {
   579  	return fmt.Sprintf("key.New(%#v)", []interface{}(k.sliceKey))
   580  }
   581  
   582  func (k pointerKey) MarshalJSON() ([]byte, error) {
   583  	return sliceToPointer(k.sliceKey).MarshalJSON()
   584  }
   585  
   586  func (k pointerKey) Equal(other interface{}) bool {
   587  	if o, ok := other.(pointerKey); ok {
   588  		return sliceEqual(k.sliceKey, o.sliceKey)
   589  	}
   590  	key, ok := other.(Key)
   591  	if !ok {
   592  		return false
   593  	}
   594  	return sliceToPointer(k.sliceKey).Equal(key.Key())
   595  }
   596  
   597  // Key interface implementation for Path
   598  func (k pathKey) Key() interface{} {
   599  	return sliceToPath(k.sliceKey)
   600  }
   601  
   602  func (k pathKey) String() string {
   603  	return sliceToPath(k.sliceKey).String()
   604  }
   605  
   606  func (k pathKey) GoString() string {
   607  	return fmt.Sprintf("key.New(%#v)", []interface{}(k.sliceKey))
   608  }
   609  
   610  func (k pathKey) MarshalJSON() ([]byte, error) {
   611  	return sliceToPath(k.sliceKey).MarshalJSON()
   612  }
   613  
   614  func (k pathKey) Equal(other interface{}) bool {
   615  	if o, ok := other.(pathKey); ok {
   616  		return sliceEqual(k.sliceKey, o.sliceKey)
   617  	}
   618  	key, ok := other.(Key)
   619  	if !ok {
   620  		return false
   621  	}
   622  	return sliceToPath(k.sliceKey).Equal(key.Key())
   623  }
   624  
   625  // Key interface implementation for nil
   626  func (k nilKey) Key() interface{} {
   627  	return nil
   628  }
   629  
   630  func (k nilKey) String() string {
   631  	return "<nil>"
   632  }
   633  
   634  func (k nilKey) GoString() string {
   635  	return "key.New(nil)"
   636  }
   637  
   638  func (k nilKey) MarshalJSON() ([]byte, error) {
   639  	return []byte("null"), nil
   640  }
   641  
   642  func (k nilKey) Equal(other interface{}) bool {
   643  	_, ok := other.(nilKey)
   644  	return ok
   645  }