deephash.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package deephash hashes a Go value recursively, in a predictable order,
  4. // without looping. The hash is only valid within the lifetime of a program.
  5. // Users should not store the hash on disk or send it over the network.
  6. // The hash is sufficiently strong and unique such that
  7. // Hash(&x) == Hash(&y) is an appropriate replacement for x == y.
  8. //
  9. // The definition of equality is identical to reflect.DeepEqual except:
  10. // - Floating-point values are compared based on the raw bits,
  11. // which means that NaNs (with the same bit pattern) are treated as equal.
  12. // - time.Time are compared based on whether they are the same instant in time
  13. // and also in the same zone offset. Monotonic measurements and zone names
  14. // are ignored as part of the hash.
  15. // - netip.Addr are compared based on a shallow comparison of the struct.
  16. //
  17. // WARNING: This package, like most of the tailscale.com Go module,
  18. // should be considered Tailscale-internal; we make no API promises.
  19. //
  20. // # Cycle detection
  21. //
  22. // This package correctly handles cycles in the value graph,
  23. // but in a way that is potentially pathological in some situations.
  24. //
  25. // The algorithm for cycle detection operates by
  26. // pushing a pointer onto a stack whenever deephash is visiting a pointer and
  27. // popping the pointer from the stack after deephash is leaving the pointer.
  28. // Before visiting a new pointer, deephash checks whether it has already been
  29. // visited on the pointer stack. If so, it hashes the index of the pointer
  30. // on the stack and avoids visiting the pointer.
  31. //
  32. // This algorithm is guaranteed to detect cycles, but may expand pointers
  33. // more often than a potential alternate algorithm that remembers all pointers
  34. // ever visited in a map. The current algorithm uses O(D) memory, where D
  35. // is the maximum depth of the recursion, while the alternate algorithm
  36. // would use O(P) memory where P is all pointers ever seen, which can be a lot,
  37. // and most of which may have nothing to do with cycles.
  38. // Also, the alternate algorithm has to deal with challenges of producing
  39. // deterministic results when pointers are visited in non-deterministic ways
  40. // such as when iterating through a Go map. The stack-based algorithm avoids
  41. // this challenge since the stack is always deterministic regardless of
  42. // non-deterministic iteration order of Go maps.
  43. //
  44. // To concretely see how this algorithm can be pathological,
  45. // consider the following data structure:
  46. //
  47. // var big *Item = ... // some large data structure that is slow to hash
  48. // var manyBig []*Item
  49. // for i := range 1000 {
  50. // manyBig = append(manyBig, &big)
  51. // }
  52. // deephash.Hash(manyBig)
  53. //
  54. // Here, the manyBig data structure is not even cyclic.
  55. // We have the same big *Item being stored multiple times in a []*Item.
  56. // When deephash hashes []*Item, it hashes each individual *Item
  57. // not realizing that it had just done the computation earlier.
  58. // To avoid the pathological situation, Item should implement [SelfHasher] and
  59. // memoize attempts to hash itself.
  60. package deephash
  61. // TODO: Add option to teach deephash to memoize the Hash result of particular types?
  62. import (
  63. "crypto/sha256"
  64. "encoding/binary"
  65. "encoding/hex"
  66. "fmt"
  67. "reflect"
  68. "sync"
  69. "time"
  70. "tailscale.com/util/hashx"
  71. "tailscale.com/util/set"
  72. )
  73. // There is much overlap between the theory of serialization and hashing.
  74. // A hash (useful for determining equality) can be produced by printing a value
  75. // and hashing the output. The format must:
  76. // * be deterministic such that the same value hashes to the same output, and
  77. // * be parsable such that the same value can be reproduced by the output.
  78. //
  79. // The logic below hashes a value by printing it to a hash.Hash.
  80. // To be parsable, it assumes that we know the Go type of each value:
  81. // * scalar types (e.g., bool or int32) are directly printed as their
  82. // underlying memory representation.
  83. // * list types (e.g., strings and slices) are prefixed by a
  84. // fixed-width length field, followed by the contents of the list.
  85. // * slices, arrays, and structs print each element/field consecutively.
  86. // * interfaces print with a 1-byte prefix indicating whether it is nil.
  87. // If non-nil, it is followed by a fixed-width field of the type index,
  88. // followed by the format of the underlying value.
  89. // * pointers print with a 1-byte prefix indicating whether the pointer is
  90. // 1) nil, 2) previously seen, or 3) newly seen. Previously seen pointers are
  91. // followed by a fixed-width field with the index of the previous pointer.
  92. // Newly seen pointers are followed by the format of the underlying value.
  93. // * maps print with a 1-byte prefix indicating whether the map pointer is
  94. // 1) nil, 2) previously seen, or 3) newly seen. Previously seen pointers
  95. // are followed by a fixed-width field of the index of the previous pointer.
  96. // Newly seen maps are printed with a fixed-width length field, followed by
  97. // a fixed-width field with the XOR of the hash of every map entry.
  98. // With a sufficiently strong hash, this value is theoretically "parsable"
  99. // by looking up the hash in a magical map that returns the set of entries
  100. // for that given hash.
  101. // SelfHasher is implemented by types that can compute their own hash
  102. // by writing values through the provided [Hasher] parameter.
  103. // Implementations must not leak the provided [Hasher].
  104. //
  105. // If the implementation of SelfHasher recursively calls [deephash.Hash],
  106. // then infinite recursion is quite likely to occur.
  107. // To avoid this, use a type definition to drop methods before calling [deephash.Hash]:
  108. //
  109. // func (v *MyType) Hash(h deephash.Hasher) {
  110. // v.hashMu.Lock()
  111. // defer v.hashMu.Unlock()
  112. // if v.dirtyHash {
  113. // type MyTypeWithoutMethods MyType // type define MyType to drop Hash method
  114. // v.dirtyHash = false // clear out dirty bit to avoid hashing over it
  115. // v.hashSum = deephash.Sum{} // clear out hashSum to avoid hashing over it
  116. // v.hashSum = deephash.Hash((*MyTypeWithoutMethods)(v))
  117. // }
  118. // h.HashSum(v.hashSum)
  119. // }
  120. //
  121. // In the above example, we acquire a lock since it is possible that deephash
  122. // is called in a concurrent manner, which implies that MyType.Hash may also
  123. // be called in a concurrent manner. Whether this lock is necessary is
  124. // application-dependent and left as an exercise to the reader.
  125. // Also, the example assumes that dirtyHash is set elsewhere by application
  126. // logic whenever a mutation is made to MyType that would alter the hash.
  127. type SelfHasher interface {
  128. Hash(Hasher)
  129. }
  130. // Hasher is a value passed to [SelfHasher.Hash] that allow implementations
  131. // to hash themselves in a structured manner.
  132. type Hasher struct{ h *hashx.Block512 }
  133. // HashBytes hashes a sequence of bytes b.
  134. // The length of b is not explicitly hashed.
  135. func (h Hasher) HashBytes(b []byte) { h.h.HashBytes(b) }
  136. // HashString hashes the string data of s
  137. // The length of s is not explicitly hashed.
  138. func (h Hasher) HashString(s string) { h.h.HashString(s) }
  139. // HashUint8 hashes a uint8.
  140. func (h Hasher) HashUint8(n uint8) { h.h.HashUint8(n) }
  141. // HashUint16 hashes a uint16.
  142. func (h Hasher) HashUint16(n uint16) { h.h.HashUint16(n) }
  143. // HashUint32 hashes a uint32.
  144. func (h Hasher) HashUint32(n uint32) { h.h.HashUint32(n) }
  145. // HashUint64 hashes a uint64.
  146. func (h Hasher) HashUint64(n uint64) { h.h.HashUint64(n) }
  147. // HashSum hashes a [Sum].
  148. func (h Hasher) HashSum(s Sum) {
  149. // NOTE: Avoid calling h.HashBytes since it escapes b,
  150. // which would force s to be heap allocated.
  151. h.h.HashUint64(binary.LittleEndian.Uint64(s.sum[0:8]))
  152. h.h.HashUint64(binary.LittleEndian.Uint64(s.sum[8:16]))
  153. h.h.HashUint64(binary.LittleEndian.Uint64(s.sum[16:24]))
  154. h.h.HashUint64(binary.LittleEndian.Uint64(s.sum[24:32]))
  155. }
  156. // hasher is reusable state for hashing a value.
  157. // Get one via hasherPool.
  158. type hasher struct {
  159. hashx.Block512
  160. visitStack visitStack
  161. }
  162. var hasherPool = &sync.Pool{
  163. New: func() any { return new(hasher) },
  164. }
  165. func (h *hasher) reset() {
  166. if h.Block512.Hash == nil {
  167. h.Block512.Hash = sha256.New()
  168. }
  169. h.Block512.Reset()
  170. }
  171. // hashType hashes a reflect.Type.
  172. // The hash is only consistent within the lifetime of a program.
  173. func (h *hasher) hashType(t reflect.Type) {
  174. // This approach relies on reflect.Type always being backed by a unique
  175. // *reflect.rtype pointer. A safer approach is to use a global sync.Map
  176. // that maps reflect.Type to some arbitrary and unique index.
  177. // While safer, it requires global state with memory that can never be GC'd.
  178. rtypeAddr := reflect.ValueOf(t).Pointer() // address of *reflect.rtype
  179. h.HashUint64(uint64(rtypeAddr))
  180. }
  181. func (h *hasher) sum() (s Sum) {
  182. h.Sum(s.sum[:0])
  183. return s
  184. }
  185. // Sum is an opaque checksum type that is comparable.
  186. type Sum struct {
  187. sum [sha256.Size]byte
  188. }
  189. func (s1 *Sum) xor(s2 Sum) {
  190. for i := range sha256.Size {
  191. s1.sum[i] ^= s2.sum[i]
  192. }
  193. }
  194. func (s Sum) String() string {
  195. // Note: if we change this, keep in sync with AppendTo
  196. return hex.EncodeToString(s.sum[:])
  197. }
  198. // AppendTo appends the string encoding of this sum (as returned by the String
  199. // method) to the provided byte slice and returns the extended buffer.
  200. func (s Sum) AppendTo(b []byte) []byte {
  201. // TODO: switch to upstream implementation if accepted:
  202. // https://github.com/golang/go/issues/53693
  203. var lb [len(s.sum) * 2]byte
  204. hex.Encode(lb[:], s.sum[:])
  205. return append(b, lb[:]...)
  206. }
  207. var (
  208. seedOnce sync.Once
  209. seed uint64
  210. )
  211. func initSeed() {
  212. seed = uint64(time.Now().UnixNano())
  213. }
  214. // Hash returns the hash of v.
  215. func Hash[T any](v *T) Sum {
  216. h := hasherPool.Get().(*hasher)
  217. defer hasherPool.Put(h)
  218. h.reset()
  219. seedOnce.Do(initSeed)
  220. h.HashUint64(seed)
  221. // Always treat the Hash input as if it were an interface by including
  222. // a hash of the type. This ensures that hashing of two different types
  223. // but with the same value structure produces different hashes.
  224. t := reflect.TypeFor[T]()
  225. h.hashType(t)
  226. if v == nil {
  227. h.HashUint8(0) // indicates nil
  228. } else {
  229. h.HashUint8(1) // indicates visiting pointer element
  230. p := pointerOf(reflect.ValueOf(v))
  231. hash := lookupTypeHasher(t)
  232. hash(h, p)
  233. }
  234. return h.sum()
  235. }
  236. // Option is an optional argument to HasherForType.
  237. type Option interface {
  238. isOption()
  239. }
  240. type fieldFilterOpt struct {
  241. t reflect.Type
  242. fields set.Set[string]
  243. includeOnMatch bool // true to include fields, false to exclude them
  244. }
  245. func (fieldFilterOpt) isOption() {}
  246. func (f fieldFilterOpt) filterStructField(sf reflect.StructField) (include bool) {
  247. if f.fields.Contains(sf.Name) {
  248. return f.includeOnMatch
  249. }
  250. return !f.includeOnMatch
  251. }
  252. // IncludeFields returns an option that modifies the hashing for T to only
  253. // include the named struct fields.
  254. //
  255. // T must be a struct type, and must match the type of the value passed to
  256. // HasherForType.
  257. func IncludeFields[T any](fields ...string) Option {
  258. return newFieldFilter[T](true, fields)
  259. }
  260. // ExcludeFields returns an option that modifies the hashing for T to include
  261. // all struct fields of T except those provided in fields.
  262. //
  263. // T must be a struct type, and must match the type of the value passed to
  264. // HasherForType.
  265. func ExcludeFields[T any](fields ...string) Option {
  266. return newFieldFilter[T](false, fields)
  267. }
  268. func newFieldFilter[T any](include bool, fields []string) Option {
  269. t := reflect.TypeFor[T]()
  270. fieldSet := set.Set[string]{}
  271. for _, f := range fields {
  272. if _, ok := t.FieldByName(f); !ok {
  273. panic(fmt.Sprintf("unknown field %q for type %v", f, t))
  274. }
  275. fieldSet.Add(f)
  276. }
  277. return fieldFilterOpt{t, fieldSet, include}
  278. }
  279. // HasherForType returns a hash that is specialized for the provided type.
  280. //
  281. // HasherForType panics if the opts are invalid for the provided type.
  282. //
  283. // Currently, at most one option can be provided (IncludeFields or
  284. // ExcludeFields) and its type must match the type of T. Those restrictions may
  285. // be removed in the future, along with documentation about their precedence
  286. // when combined.
  287. func HasherForType[T any](opts ...Option) func(*T) Sum {
  288. seedOnce.Do(initSeed)
  289. if len(opts) > 1 {
  290. panic("HasherForType only accepts one optional argument") // for now
  291. }
  292. t := reflect.TypeFor[T]()
  293. var hash typeHasherFunc
  294. for _, o := range opts {
  295. switch o := o.(type) {
  296. default:
  297. panic(fmt.Sprintf("unknown HasherOpt %T", o))
  298. case fieldFilterOpt:
  299. if t.Kind() != reflect.Struct {
  300. panic("HasherForStructTypeWithFieldFilter requires T of kind struct")
  301. }
  302. if t != o.t {
  303. panic(fmt.Sprintf("field filter for type %v does not match HasherForType type %v", o.t, t))
  304. }
  305. hash = makeStructHasher(t, o.filterStructField)
  306. }
  307. }
  308. if hash == nil {
  309. hash = lookupTypeHasher(t)
  310. }
  311. return func(v *T) (s Sum) {
  312. // This logic is identical to Hash, but pull out a few statements.
  313. h := hasherPool.Get().(*hasher)
  314. defer hasherPool.Put(h)
  315. h.reset()
  316. h.HashUint64(seed)
  317. h.hashType(t)
  318. if v == nil {
  319. h.HashUint8(0) // indicates nil
  320. } else {
  321. h.HashUint8(1) // indicates visiting pointer element
  322. p := pointerOf(reflect.ValueOf(v))
  323. hash(h, p)
  324. }
  325. return h.sum()
  326. }
  327. }
  328. // Update sets last to the hash of v and reports whether its value changed.
  329. func Update[T any](last *Sum, v *T) (changed bool) {
  330. sum := Hash(v)
  331. changed = sum != *last
  332. if changed {
  333. *last = sum
  334. }
  335. return changed
  336. }
  337. // typeHasherFunc hashes the value pointed at by p for a given type.
  338. // For example, if t is a bool, then p is a *bool.
  339. // The provided pointer must always be non-nil.
  340. type typeHasherFunc func(h *hasher, p pointer)
  341. var typeHasherCache sync.Map // map[reflect.Type]typeHasherFunc
  342. func lookupTypeHasher(t reflect.Type) typeHasherFunc {
  343. if v, ok := typeHasherCache.Load(t); ok {
  344. return v.(typeHasherFunc)
  345. }
  346. hash := makeTypeHasher(t)
  347. v, _ := typeHasherCache.LoadOrStore(t, hash)
  348. return v.(typeHasherFunc)
  349. }
  350. func makeTypeHasher(t reflect.Type) typeHasherFunc {
  351. // Types with specific hashing.
  352. switch t {
  353. case timeTimeType:
  354. return hashTime
  355. case netipAddrType:
  356. return hashAddr
  357. }
  358. // Types that implement their own hashing.
  359. if t.Kind() != reflect.Pointer && t.Kind() != reflect.Interface {
  360. // A method can be implemented on either the value receiver or pointer receiver.
  361. if t.Implements(selfHasherType) || reflect.PointerTo(t).Implements(selfHasherType) {
  362. return makeSelfHasher(t)
  363. }
  364. }
  365. // Types that can have their memory representation directly hashed.
  366. if typeIsMemHashable(t) {
  367. return makeMemHasher(t.Size())
  368. }
  369. switch t.Kind() {
  370. case reflect.String:
  371. return hashString
  372. case reflect.Array:
  373. return makeArrayHasher(t)
  374. case reflect.Slice:
  375. return makeSliceHasher(t)
  376. case reflect.Struct:
  377. return makeStructHasher(t, keepAllStructFields)
  378. case reflect.Map:
  379. return makeMapHasher(t)
  380. case reflect.Pointer:
  381. return makePointerHasher(t)
  382. case reflect.Interface:
  383. return makeInterfaceHasher(t)
  384. default: // Func, Chan, UnsafePointer
  385. return func(*hasher, pointer) {}
  386. }
  387. }
  388. func hashTime(h *hasher, p pointer) {
  389. // Include the zone offset (but not the name) to keep
  390. // Hash(t1) == Hash(t2) being semantically equivalent to
  391. // t1.Format(time.RFC3339Nano) == t2.Format(time.RFC3339Nano).
  392. t := *p.asTime()
  393. _, offset := t.Zone()
  394. h.HashUint64(uint64(t.Unix()))
  395. h.HashUint32(uint32(t.Nanosecond()))
  396. h.HashUint32(uint32(offset))
  397. }
  398. func hashAddr(h *hasher, p pointer) {
  399. // The formatting of netip.Addr covers the
  400. // IP version, the address, and the optional zone name (for v6).
  401. // This is equivalent to a1.MarshalBinary() == a2.MarshalBinary().
  402. ip := *p.asAddr()
  403. switch {
  404. case !ip.IsValid():
  405. h.HashUint64(0)
  406. case ip.Is4():
  407. b := ip.As4()
  408. h.HashUint64(4)
  409. h.HashUint32(binary.LittleEndian.Uint32(b[:]))
  410. case ip.Is6():
  411. b := ip.As16()
  412. z := ip.Zone()
  413. h.HashUint64(16 + uint64(len(z)))
  414. h.HashUint64(binary.LittleEndian.Uint64(b[:8]))
  415. h.HashUint64(binary.LittleEndian.Uint64(b[8:]))
  416. h.HashString(z)
  417. }
  418. }
  419. func makeSelfHasher(t reflect.Type) typeHasherFunc {
  420. return func(h *hasher, p pointer) {
  421. p.asValue(t).Interface().(SelfHasher).Hash(Hasher{&h.Block512})
  422. }
  423. }
  424. func hashString(h *hasher, p pointer) {
  425. s := *p.asString()
  426. h.HashUint64(uint64(len(s)))
  427. h.HashString(s)
  428. }
  429. func makeMemHasher(n uintptr) typeHasherFunc {
  430. return func(h *hasher, p pointer) {
  431. h.HashBytes(p.asMemory(n))
  432. }
  433. }
  434. func makeArrayHasher(t reflect.Type) typeHasherFunc {
  435. var once sync.Once
  436. var hashElem typeHasherFunc
  437. init := func() {
  438. hashElem = lookupTypeHasher(t.Elem())
  439. }
  440. n := t.Len() // number of array elements
  441. nb := t.Elem().Size() // byte size of each array element
  442. return func(h *hasher, p pointer) {
  443. once.Do(init)
  444. for i := range n {
  445. hashElem(h, p.arrayIndex(i, nb))
  446. }
  447. }
  448. }
  449. func makeSliceHasher(t reflect.Type) typeHasherFunc {
  450. nb := t.Elem().Size() // byte size of each slice element
  451. if typeIsMemHashable(t.Elem()) {
  452. return func(h *hasher, p pointer) {
  453. pa := p.sliceArray()
  454. if pa.isNil() {
  455. h.HashUint8(0) // indicates nil
  456. return
  457. }
  458. h.HashUint8(1) // indicates visiting slice
  459. n := p.sliceLen()
  460. b := pa.asMemory(uintptr(n) * nb)
  461. h.HashUint64(uint64(n))
  462. h.HashBytes(b)
  463. }
  464. }
  465. var once sync.Once
  466. var hashElem typeHasherFunc
  467. init := func() {
  468. hashElem = lookupTypeHasher(t.Elem())
  469. if typeIsRecursive(t) {
  470. hashElemDefault := hashElem
  471. hashElem = func(h *hasher, p pointer) {
  472. if idx, ok := h.visitStack.seen(p.p); ok {
  473. h.HashUint8(2) // indicates cycle
  474. h.HashUint64(uint64(idx))
  475. return
  476. }
  477. h.HashUint8(1) // indicates visiting slice element
  478. h.visitStack.push(p.p)
  479. defer h.visitStack.pop(p.p)
  480. hashElemDefault(h, p)
  481. }
  482. }
  483. }
  484. return func(h *hasher, p pointer) {
  485. pa := p.sliceArray()
  486. if pa.isNil() {
  487. h.HashUint8(0) // indicates nil
  488. return
  489. }
  490. once.Do(init)
  491. h.HashUint8(1) // indicates visiting slice
  492. n := p.sliceLen()
  493. h.HashUint64(uint64(n))
  494. for i := range n {
  495. pe := pa.arrayIndex(i, nb)
  496. hashElem(h, pe)
  497. }
  498. }
  499. }
  500. func keepAllStructFields(keepField reflect.StructField) bool { return true }
  501. func makeStructHasher(t reflect.Type, keepField func(reflect.StructField) bool) typeHasherFunc {
  502. type fieldHasher struct {
  503. idx int // index of field for reflect.Type.Field(n); negative if memory is directly hashable
  504. keep bool
  505. hash typeHasherFunc // only valid if idx is not negative
  506. offset uintptr
  507. size uintptr
  508. }
  509. var once sync.Once
  510. var fields []fieldHasher
  511. init := func() {
  512. for i, numField := 0, t.NumField(); i < numField; i++ {
  513. sf := t.Field(i)
  514. f := fieldHasher{i, keepField(sf), nil, sf.Offset, sf.Type.Size()}
  515. if f.keep && typeIsMemHashable(sf.Type) {
  516. f.idx = -1
  517. }
  518. // Combine with previous field if both contiguous and mem-hashable.
  519. if f.idx < 0 && len(fields) > 0 {
  520. if last := &fields[len(fields)-1]; last.idx < 0 && last.offset+last.size == f.offset {
  521. last.size += f.size
  522. continue
  523. }
  524. }
  525. fields = append(fields, f)
  526. }
  527. for i, f := range fields {
  528. if f.idx >= 0 {
  529. fields[i].hash = lookupTypeHasher(t.Field(f.idx).Type)
  530. }
  531. }
  532. }
  533. return func(h *hasher, p pointer) {
  534. once.Do(init)
  535. for _, field := range fields {
  536. if !field.keep {
  537. continue
  538. }
  539. pf := p.structField(field.idx, field.offset, field.size)
  540. if field.idx < 0 {
  541. h.HashBytes(pf.asMemory(field.size))
  542. } else {
  543. field.hash(h, pf)
  544. }
  545. }
  546. }
  547. }
  548. func makeMapHasher(t reflect.Type) typeHasherFunc {
  549. var once sync.Once
  550. var hashKey, hashValue typeHasherFunc
  551. var isRecursive bool
  552. init := func() {
  553. hashKey = lookupTypeHasher(t.Key())
  554. hashValue = lookupTypeHasher(t.Elem())
  555. isRecursive = typeIsRecursive(t)
  556. }
  557. return func(h *hasher, p pointer) {
  558. v := p.asValue(t).Elem() // reflect.Map kind
  559. if v.IsNil() {
  560. h.HashUint8(0) // indicates nil
  561. return
  562. }
  563. once.Do(init)
  564. if isRecursive {
  565. pm := v.UnsafePointer() // underlying pointer of map
  566. if idx, ok := h.visitStack.seen(pm); ok {
  567. h.HashUint8(2) // indicates cycle
  568. h.HashUint64(uint64(idx))
  569. return
  570. }
  571. h.visitStack.push(pm)
  572. defer h.visitStack.pop(pm)
  573. }
  574. h.HashUint8(1) // indicates visiting map entries
  575. h.HashUint64(uint64(v.Len()))
  576. mh := mapHasherPool.Get().(*mapHasher)
  577. defer mapHasherPool.Put(mh)
  578. // Hash a map in a sort-free manner.
  579. // It relies on a map being a an unordered set of KV entries.
  580. // So long as we hash each KV entry together, we can XOR all the
  581. // individual hashes to produce a unique hash for the entire map.
  582. k := mh.valKey.get(v.Type().Key())
  583. e := mh.valElem.get(v.Type().Elem())
  584. mh.sum = Sum{}
  585. mh.h.visitStack = h.visitStack // always use the parent's visit stack to avoid cycles
  586. for iter := v.MapRange(); iter.Next(); {
  587. k.SetIterKey(iter)
  588. e.SetIterValue(iter)
  589. mh.h.reset()
  590. hashKey(&mh.h, pointerOf(k.Addr()))
  591. hashValue(&mh.h, pointerOf(e.Addr()))
  592. mh.sum.xor(mh.h.sum())
  593. }
  594. h.HashBytes(mh.sum.sum[:])
  595. }
  596. }
  597. func makePointerHasher(t reflect.Type) typeHasherFunc {
  598. var once sync.Once
  599. var hashElem typeHasherFunc
  600. var isRecursive bool
  601. init := func() {
  602. hashElem = lookupTypeHasher(t.Elem())
  603. isRecursive = typeIsRecursive(t)
  604. }
  605. return func(h *hasher, p pointer) {
  606. pe := p.pointerElem()
  607. if pe.isNil() {
  608. h.HashUint8(0) // indicates nil
  609. return
  610. }
  611. once.Do(init)
  612. if isRecursive {
  613. if idx, ok := h.visitStack.seen(pe.p); ok {
  614. h.HashUint8(2) // indicates cycle
  615. h.HashUint64(uint64(idx))
  616. return
  617. }
  618. h.visitStack.push(pe.p)
  619. defer h.visitStack.pop(pe.p)
  620. }
  621. h.HashUint8(1) // indicates visiting a pointer element
  622. hashElem(h, pe)
  623. }
  624. }
  625. func makeInterfaceHasher(t reflect.Type) typeHasherFunc {
  626. return func(h *hasher, p pointer) {
  627. v := p.asValue(t).Elem() // reflect.Interface kind
  628. if v.IsNil() {
  629. h.HashUint8(0) // indicates nil
  630. return
  631. }
  632. h.HashUint8(1) // indicates visiting an interface value
  633. v = v.Elem()
  634. t := v.Type()
  635. h.hashType(t)
  636. va := reflect.New(t).Elem()
  637. va.Set(v)
  638. hashElem := lookupTypeHasher(t)
  639. hashElem(h, pointerOf(va.Addr()))
  640. }
  641. }
  642. type mapHasher struct {
  643. h hasher
  644. valKey valueCache
  645. valElem valueCache
  646. sum Sum
  647. }
  648. var mapHasherPool = &sync.Pool{
  649. New: func() any { return new(mapHasher) },
  650. }
  651. type valueCache map[reflect.Type]reflect.Value
  652. // get returns an addressable reflect.Value for the given type.
  653. func (c *valueCache) get(t reflect.Type) reflect.Value {
  654. v, ok := (*c)[t]
  655. if !ok {
  656. v = reflect.New(t).Elem()
  657. if *c == nil {
  658. *c = make(valueCache)
  659. }
  660. (*c)[t] = v
  661. }
  662. return v
  663. }