const std = @import("std"); pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type { return struct { load_maximum: f32, buckets_used: usize, buckets: []Bucket, /// /// /// const Bucket = struct { maybe_entry: ?struct { key: Key, value: Value, }, maybe_next_index: ?usize, }; /// /// /// const Self = @This(); /// /// /// pub fn delete(self: Self, key: Key) bool { _ = key; _ = self; } /// /// /// pub fn insert(self: Self, key: Key, value: Value) InsertError!void { if ((@intToFloat(f32, self.buckets_used) / @intToFloat( f32, self.buckets.len)) >= self.load_maximum) try self.rehash(); var hash = @mod(key_context.hash(key), self.buckets.len); while (true) { const bucket = &(self.buckets[hash]); const entry = &(bucket.maybe_entry orelse { bucket.maybe_entry = .{ .key = key, .value = value }; }); if (key_context.equals(entry.key, key)) return error.KeyExists; hash = @mod(hashHash(hash), self.buckets.len); } } /// /// Searches for a value indexed with `key` in `self`, returning it or `null` if no matching /// entry was found. /// pub fn lookup(self: Self, key: Key) ?*Value { var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]); if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) return &entry.value; while (bucket.maybe_next_index) |index| { bucket = &(self.buckets[index]); if (bucket.maybe_entry) |*entry| if (key_context.equals(entry.key, key)) return &entry.value; } return null; } }; } /// /// /// pub const InsertError = std.mem.Allocator || error { KeyExists, }; pub fn KeyContext(comptime Key: type) type { return struct { hash: fn (Key) usize, equals: fn (Key, Key) bool, }; } fn equalsString(this_string: []const u8, that_string: []const u8) bool { return std.mem.eql(u8, this_string, that_string); } fn hashString(string: []const u8) usize { var hash = @as(usize, 5381); for (string) |byte| hash = ((hash << 5) + hash) + byte; return hash; } pub const string_context = KeyContext([]const u8){ .hash = hashString, .equals = equalsString, };