package cuckoo type entry[K, V any] struct { key K value V } type slot[K, V any] struct { entry[K, V] occupied bool } type table[K, V any] struct { hash Hash[K] slots []slot[K, V] capacity, size uint64 compare EqualFunc[K] } // location determines where in the bucket a certain key would be placed. If the // capacity is 0, this will panic. func (t table[K, V]) location(key K) uint64 { return t.hash(key) % t.capacity } func (t table[K, V]) get(key K) (value V, found bool) { if t.capacity == 0 { return } slot := t.slots[t.location(key)] return slot.value, slot.occupied && t.compare(slot.key, key) } func (t *table[K, V]) drop(key K) (occupied bool) { if t.capacity == 0 { return } slot := &t.slots[t.location(key)] if slot.occupied && t.compare(slot.key, key) { slot.occupied = false t.size-- return true } return false } func (t *table[K, V]) resize(capacity uint64) { t.slots = make([]slot[K, V], capacity) t.capacity = capacity t.size = 0 } func (t table[K, V]) update(key K, value V) (updated bool) { if t.capacity == 0 { return } slot := &t.slots[t.location(key)] if slot.occupied && t.compare(slot.key, key) { slot.value = value return true } return false } func (t *table[K, V]) evict(insertion entry[K, V]) (evicted entry[K, V], eviction bool) { if t.capacity == 0 { return insertion, true } slot := &t.slots[t.location(insertion.key)] if !slot.occupied { slot.entry = insertion slot.occupied = true t.size++ return } if t.compare(slot.key, insertion.key) { slot.value = insertion.value return } insertion, slot.entry = slot.entry, insertion return insertion, true } func newTable[K, V any](capacity uint64, hash Hash[K], compare EqualFunc[K]) table[K, V] { return table[K, V]{ hash: hash, capacity: capacity, compare: compare, size: 0, slots: make([]slot[K, V], capacity), } }