key.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. package key
  5. import (
  6. "encoding/json"
  7. "fmt"
  8. "math"
  9. "strconv"
  10. "notabug.org/themusicgod1/goarista/value"
  11. )
  12. // Key represents the Key in the updates and deletes of the Notification
  13. // objects. The only reason this exists is that Go won't let us define
  14. // our own hash function for non-hashable types, and unfortunately we
  15. // need to be able to index maps by map[string]interface{} objects
  16. // and slices by []interface{} objects.
  17. type Key interface {
  18. Key() interface{}
  19. String() string
  20. Equal(other interface{}) bool
  21. }
  22. // compositeKey allows storing a map[string]interface{} or []interface{} as a key
  23. // in a Go map. This is useful when the key isn't a fixed data structure known
  24. // at compile time but rather something generic, like a bag of key-value pairs
  25. // or a list of elements. Go does not allow storing a map or slice inside the
  26. // key of a map, because maps and slices are not comparable or hashable, and
  27. // keys in maps and slice elements must be both. This file is a hack specific
  28. // to the 'gc' implementation of Go (which is the one most people use when they
  29. // use Go), to bypass this check, by abusing reflection to override how Go
  30. // compares compositeKey for equality or how it's hashed. The values allowed in
  31. // this map are only the types whitelisted in New() as well as map[Key]interface{}
  32. // and []interface{}.
  33. //
  34. // See also https://github.com/golang/go/issues/283
  35. type compositeKey struct {
  36. // This value must always be set to the sentinel constant above.
  37. sentinel uintptr
  38. m map[string]interface{}
  39. s []interface{}
  40. }
  41. type interfaceKey struct {
  42. key interface{}
  43. }
  44. type strKey string
  45. type int8Key int8
  46. type int16Key int16
  47. type int32Key int32
  48. type int64Key int64
  49. type uint8Key int8
  50. type uint16Key int16
  51. type uint32Key int32
  52. type uint64Key int64
  53. type float32Key float32
  54. type float64Key float64
  55. type boolKey bool
  56. type pointerKey compositeKey
  57. func pointerToSlice(ptr Pointer) []interface{} {
  58. path := ptr.Pointer()
  59. s := make([]interface{}, len(path))
  60. for i, element := range path {
  61. s[i] = element.Key()
  62. }
  63. return s
  64. }
  65. func sliceToPointer(s []interface{}) pointer {
  66. path := make(Path, len(s))
  67. for i, intf := range s {
  68. path[i] = New(intf)
  69. }
  70. return pointer(path)
  71. }
  72. // New wraps the given value in a Key.
  73. // This function panics if the value passed in isn't allowed in a Key or
  74. // doesn't implement value.Value.
  75. func New(intf interface{}) Key {
  76. switch t := intf.(type) {
  77. case map[string]interface{}:
  78. return compositeKey{sentinel: sentinel, m: t}
  79. case []interface{}:
  80. return compositeKey{sentinel: sentinel, s: t}
  81. case string:
  82. return strKey(t)
  83. case int8:
  84. return int8Key(t)
  85. case int16:
  86. return int16Key(t)
  87. case int32:
  88. return int32Key(t)
  89. case int64:
  90. return int64Key(t)
  91. case uint8:
  92. return uint8Key(t)
  93. case uint16:
  94. return uint16Key(t)
  95. case uint32:
  96. return uint32Key(t)
  97. case uint64:
  98. return uint64Key(t)
  99. case float32:
  100. return float32Key(t)
  101. case float64:
  102. return float64Key(t)
  103. case bool:
  104. return boolKey(t)
  105. case Pointer:
  106. return pointerKey{sentinel: sentinel, s: pointerToSlice(t)}
  107. case value.Value:
  108. return interfaceKey{key: intf}
  109. default:
  110. panic(fmt.Sprintf("Invalid type for key: %T", intf))
  111. }
  112. }
  113. func (k interfaceKey) Key() interface{} {
  114. return k.key
  115. }
  116. func (k interfaceKey) String() string {
  117. return stringify(k.key)
  118. }
  119. func (k interfaceKey) GoString() string {
  120. return fmt.Sprintf("key.New(%#v)", k.Key())
  121. }
  122. func (k interfaceKey) MarshalJSON() ([]byte, error) {
  123. return json.Marshal(k.Key())
  124. }
  125. func (k interfaceKey) Equal(other interface{}) bool {
  126. o, ok := other.(interfaceKey)
  127. return ok && keyEqual(k.key, o.key)
  128. }
  129. // Comparable types have an equality-testing method.
  130. type Comparable interface {
  131. // Equal returns true if this object is equal to the other one.
  132. Equal(other interface{}) bool
  133. }
  134. func mapStringEqual(a, b map[string]interface{}) bool {
  135. if len(a) != len(b) {
  136. return false
  137. }
  138. for k, av := range a {
  139. if bv, ok := b[k]; !ok || !keyEqual(av, bv) {
  140. return false
  141. }
  142. }
  143. return true
  144. }
  145. func sliceEqual(a, b []interface{}) bool {
  146. if len(a) != len(b) {
  147. return false
  148. }
  149. for i, v := range a {
  150. if !keyEqual(v, b[i]) {
  151. return false
  152. }
  153. }
  154. return true
  155. }
  156. func keyEqual(a, b interface{}) bool {
  157. switch a := a.(type) {
  158. case map[string]interface{}:
  159. b, ok := b.(map[string]interface{})
  160. return ok && mapStringEqual(a, b)
  161. case map[Key]interface{}:
  162. b, ok := b.(map[Key]interface{})
  163. if !ok || len(a) != len(b) {
  164. return false
  165. }
  166. for k, av := range a {
  167. if bv, ok := b[k]; !ok || !keyEqual(av, bv) {
  168. return false
  169. }
  170. }
  171. return true
  172. case []interface{}:
  173. b, ok := b.([]interface{})
  174. return ok && sliceEqual(a, b)
  175. case Comparable:
  176. return a.Equal(b)
  177. case Pointer:
  178. b, ok := b.(Pointer)
  179. if !ok {
  180. return false
  181. }
  182. x, y := a.Pointer(), b.Pointer()
  183. if len(x) != len(y) {
  184. return false
  185. }
  186. for i := range x {
  187. if !x[i].Equal(y[i]) {
  188. return false
  189. }
  190. }
  191. return true
  192. }
  193. return a == b
  194. }
  195. // Key interface implementation for map[string]interface{} and []interface{}
  196. func (k compositeKey) Key() interface{} {
  197. if k.m != nil {
  198. return k.m
  199. }
  200. return k.s
  201. }
  202. func (k compositeKey) String() string {
  203. return stringify(k.Key())
  204. }
  205. func (k compositeKey) GoString() string {
  206. return fmt.Sprintf("key.New(%#v)", k.Key())
  207. }
  208. func (k compositeKey) MarshalJSON() ([]byte, error) {
  209. return json.Marshal(k.Key())
  210. }
  211. func (k compositeKey) Equal(other interface{}) bool {
  212. o, ok := other.(compositeKey)
  213. if k.m != nil {
  214. return ok && mapStringEqual(k.m, o.m)
  215. }
  216. return ok && sliceEqual(k.s, o.s)
  217. }
  218. func (k strKey) Key() interface{} {
  219. return string(k)
  220. }
  221. func (k strKey) String() string {
  222. return string(k)
  223. }
  224. func (k strKey) GoString() string {
  225. return fmt.Sprintf("key.New(%q)", string(k))
  226. }
  227. func (k strKey) MarshalJSON() ([]byte, error) {
  228. return json.Marshal(escape(string(k)))
  229. }
  230. func (k strKey) Equal(other interface{}) bool {
  231. o, ok := other.(strKey)
  232. return ok && k == o
  233. }
  234. // Key interface implementation for int8
  235. func (k int8Key) Key() interface{} {
  236. return int8(k)
  237. }
  238. func (k int8Key) String() string {
  239. return strconv.FormatInt(int64(k), 10)
  240. }
  241. func (k int8Key) GoString() string {
  242. return fmt.Sprintf("key.New(%d)", int8(k))
  243. }
  244. func (k int8Key) MarshalJSON() ([]byte, error) {
  245. return []byte(strconv.FormatInt(int64(k), 10)), nil
  246. }
  247. func (k int8Key) Equal(other interface{}) bool {
  248. o, ok := other.(int8Key)
  249. return ok && k == o
  250. }
  251. // Key interface implementation for int16
  252. func (k int16Key) Key() interface{} {
  253. return int16(k)
  254. }
  255. func (k int16Key) String() string {
  256. return strconv.FormatInt(int64(k), 10)
  257. }
  258. func (k int16Key) GoString() string {
  259. return fmt.Sprintf("key.New(%d)", int16(k))
  260. }
  261. func (k int16Key) MarshalJSON() ([]byte, error) {
  262. return []byte(strconv.FormatInt(int64(k), 10)), nil
  263. }
  264. func (k int16Key) Equal(other interface{}) bool {
  265. o, ok := other.(int16Key)
  266. return ok && k == o
  267. }
  268. // Key interface implementation for int32
  269. func (k int32Key) Key() interface{} {
  270. return int32(k)
  271. }
  272. func (k int32Key) String() string {
  273. return strconv.FormatInt(int64(k), 10)
  274. }
  275. func (k int32Key) GoString() string {
  276. return fmt.Sprintf("key.New(%d)", int32(k))
  277. }
  278. func (k int32Key) MarshalJSON() ([]byte, error) {
  279. return []byte(strconv.FormatInt(int64(k), 10)), nil
  280. }
  281. func (k int32Key) Equal(other interface{}) bool {
  282. o, ok := other.(int32Key)
  283. return ok && k == o
  284. }
  285. // Key interface implementation for int64
  286. func (k int64Key) Key() interface{} {
  287. return int64(k)
  288. }
  289. func (k int64Key) String() string {
  290. return strconv.FormatInt(int64(k), 10)
  291. }
  292. func (k int64Key) GoString() string {
  293. return fmt.Sprintf("key.New(%d)", int64(k))
  294. }
  295. func (k int64Key) MarshalJSON() ([]byte, error) {
  296. return []byte(strconv.FormatInt(int64(k), 10)), nil
  297. }
  298. func (k int64Key) Equal(other interface{}) bool {
  299. o, ok := other.(int64Key)
  300. return ok && k == o
  301. }
  302. // Key interface implementation for uint8
  303. func (k uint8Key) Key() interface{} {
  304. return uint8(k)
  305. }
  306. func (k uint8Key) String() string {
  307. return strconv.FormatUint(uint64(k), 10)
  308. }
  309. func (k uint8Key) GoString() string {
  310. return fmt.Sprintf("key.New(%d)", uint8(k))
  311. }
  312. func (k uint8Key) MarshalJSON() ([]byte, error) {
  313. return []byte(strconv.FormatUint(uint64(k), 10)), nil
  314. }
  315. func (k uint8Key) Equal(other interface{}) bool {
  316. o, ok := other.(uint8Key)
  317. return ok && k == o
  318. }
  319. // Key interface implementation for uint16
  320. func (k uint16Key) Key() interface{} {
  321. return uint16(k)
  322. }
  323. func (k uint16Key) String() string {
  324. return strconv.FormatUint(uint64(k), 10)
  325. }
  326. func (k uint16Key) GoString() string {
  327. return fmt.Sprintf("key.New(%d)", uint16(k))
  328. }
  329. func (k uint16Key) MarshalJSON() ([]byte, error) {
  330. return []byte(strconv.FormatUint(uint64(k), 10)), nil
  331. }
  332. func (k uint16Key) Equal(other interface{}) bool {
  333. o, ok := other.(uint16Key)
  334. return ok && k == o
  335. }
  336. // Key interface implementation for uint32
  337. func (k uint32Key) Key() interface{} {
  338. return uint32(k)
  339. }
  340. func (k uint32Key) String() string {
  341. return strconv.FormatUint(uint64(k), 10)
  342. }
  343. func (k uint32Key) GoString() string {
  344. return fmt.Sprintf("key.New(%d)", uint32(k))
  345. }
  346. func (k uint32Key) MarshalJSON() ([]byte, error) {
  347. return []byte(strconv.FormatUint(uint64(k), 10)), nil
  348. }
  349. func (k uint32Key) Equal(other interface{}) bool {
  350. o, ok := other.(uint32Key)
  351. return ok && k == o
  352. }
  353. // Key interface implementation for uint64
  354. func (k uint64Key) Key() interface{} {
  355. return uint64(k)
  356. }
  357. func (k uint64Key) String() string {
  358. return strconv.FormatUint(uint64(k), 10)
  359. }
  360. func (k uint64Key) GoString() string {
  361. return fmt.Sprintf("key.New(%d)", uint64(k))
  362. }
  363. func (k uint64Key) MarshalJSON() ([]byte, error) {
  364. return []byte(strconv.FormatUint(uint64(k), 10)), nil
  365. }
  366. func (k uint64Key) Equal(other interface{}) bool {
  367. o, ok := other.(uint64Key)
  368. return ok && k == o
  369. }
  370. // Key interface implementation for float32
  371. func (k float32Key) Key() interface{} {
  372. return float32(k)
  373. }
  374. func (k float32Key) String() string {
  375. return "f" + strconv.FormatInt(int64(math.Float32bits(float32(k))), 10)
  376. }
  377. func (k float32Key) GoString() string {
  378. return fmt.Sprintf("key.New(%v)", float32(k))
  379. }
  380. func (k float32Key) MarshalJSON() ([]byte, error) {
  381. return []byte(strconv.FormatFloat(float64(k), 'g', -1, 32)), nil
  382. }
  383. func (k float32Key) Equal(other interface{}) bool {
  384. o, ok := other.(float32Key)
  385. return ok && k == o
  386. }
  387. // Key interface implementation for float64
  388. func (k float64Key) Key() interface{} {
  389. return float64(k)
  390. }
  391. func (k float64Key) String() string {
  392. return "f" + strconv.FormatInt(int64(math.Float64bits(float64(k))), 10)
  393. }
  394. func (k float64Key) GoString() string {
  395. return fmt.Sprintf("key.New(%v)", float64(k))
  396. }
  397. func (k float64Key) MarshalJSON() ([]byte, error) {
  398. return []byte(strconv.FormatFloat(float64(k), 'g', -1, 64)), nil
  399. }
  400. func (k float64Key) Equal(other interface{}) bool {
  401. o, ok := other.(float64Key)
  402. return ok && k == o
  403. }
  404. // Key interface implementation for bool
  405. func (k boolKey) Key() interface{} {
  406. return bool(k)
  407. }
  408. func (k boolKey) String() string {
  409. return strconv.FormatBool(bool(k))
  410. }
  411. func (k boolKey) GoString() string {
  412. return fmt.Sprintf("key.New(%v)", bool(k))
  413. }
  414. func (k boolKey) MarshalJSON() ([]byte, error) {
  415. return []byte(strconv.FormatBool(bool(k))), nil
  416. }
  417. func (k boolKey) Equal(other interface{}) bool {
  418. o, ok := other.(boolKey)
  419. return ok && k == o
  420. }
  421. // Key interface implementation for Pointer
  422. func (k pointerKey) Key() interface{} {
  423. return sliceToPointer(k.s)
  424. }
  425. func (k pointerKey) String() string {
  426. return sliceToPointer(k.s).String()
  427. }
  428. func (k pointerKey) GoString() string {
  429. return fmt.Sprintf("key.New(%#v)", k.s)
  430. }
  431. func (k pointerKey) MarshalJSON() ([]byte, error) {
  432. return sliceToPointer(k.s).MarshalJSON()
  433. }
  434. func (k pointerKey) Equal(other interface{}) bool {
  435. o, ok := other.(pointerKey)
  436. return ok && sliceEqual(k.s, o.s)
  437. }