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 }