package cuckoo // An Entry is a key-value pair. type Entry[K, V any] struct { key K value V } type slot[K, V any] struct { Entry[K, V] occupied bool } type bucket[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 (b bucket[K, V]) location(key K) uint64 { return b.hash(key) % b.capacity } func (b bucket[K, V]) get(key K) (value V, found bool) { if b.capacity == 0 { return } slot := b.slots[b.location(key)] return slot.value, slot.occupied && b.compare(slot.key, key) } func (b *bucket[K, V]) drop(key K) (occupied bool) { if b.capacity == 0 { return } slot := &b.slots[b.location(key)] if slot.occupied && b.compare(slot.key, key) { slot.occupied = false b.size-- return true } return false } func (b *bucket[K, V]) resized(capacity uint64) bucket[K, V] { return bucket[K, V]{ slots: make([]slot[K, V], capacity), capacity: capacity, hash: b.hash, compare: b.compare, } } func (b bucket[K, V]) update(key K, value V) (updated bool) { if b.capacity == 0 { return } slot := &b.slots[b.location(key)] if slot.occupied && b.compare(slot.key, key) { slot.value = value return true } return false } func (b *bucket[K, V]) insert(insertion Entry[K, V]) (evicted Entry[K, V], eviction bool) { if b.capacity == 0 { return insertion, true } slot := &b.slots[b.location(insertion.key)] if !slot.occupied { slot.Entry = insertion slot.occupied = true b.size++ return } if b.compare(slot.key, insertion.key) { slot.value = insertion.value return } insertion, slot.Entry = slot.Entry, insertion return insertion, true } func newBucket[K, V any](capacity uint64, hash Hash[K], compare EqualFunc[K]) bucket[K, V] { return bucket[K, V]{ hash: hash, capacity: capacity, compare: compare, size: 0, slots: make([]slot[K, V], capacity), } }