pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult {
const header = self.index_header orelse {
// Linear scan.
const h = if (store_hash) checkedHash(ctx, key) else {};
const slice = self.entries.slice();
const hashes_array = slice.items(.hash);
const keys_array = slice.items(.key);
for (keys_array, 0..) |*item_key, i| {
if (hashes_array[i] == h and checkedEql(ctx, key, item_key.*, i)) {
return GetOrPutResult{
.key_ptr = item_key,
.value_ptr = &slice.items(.value)[i],
.found_existing = true,
.index = i,
};
}
}
const index = self.entries.addOneAssumeCapacity();
// The slice length changed, so we directly index the pointer.
if (store_hash) hashes_array.ptr[index] = h;
return GetOrPutResult{
.key_ptr = &keys_array.ptr[index],
.value_ptr = &slice.items(.value).ptr[index],
.found_existing = false,
.index = index,
};
};
switch (header.capacityIndexType()) {
.u8 => return self.getOrPutInternal(key, ctx, header, u8),
.u16 => return self.getOrPutInternal(key, ctx, header, u16),
.u32 => return self.getOrPutInternal(key, ctx, header, u32),
}
}
If there is an existing item with
key, then the resultEntrypointers point to it, and found_existing is true. Otherwise, puts a new item with undefined key and value, and theEntrypointers point to it. Caller must then initialize both the key and the value. If a new entry needs to be stored, this function asserts there is enough capacity to store it.