| ... | @@ -183,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -183,6 +183,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 183 | return putAssumeCapacity(self, key, value); | 183 | return putAssumeCapacity(self, key, value); |
| 184 | } | 184 | } |
| 185 | | 185 | |
| | 186 | /// Calls put() and asserts that no kv pair is clobbered. |
| | 187 | pub fn putNoClobber(self: *Self, key: K, value: V) !void { |
| | 188 | assert((try self.put(key, value)) == null); |
| | 189 | } |
| | 190 | |
| 186 | pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV { | 191 | pub fn putAssumeCapacity(self: *Self, key: K, value: V) ?KV { |
| 187 | assert(self.count() < self.entries.len); | 192 | assert(self.count() < self.entries.len); |
| 188 | self.incrementModificationCount(); | 193 | self.incrementModificationCount(); |
| ... | @@ -203,6 +208,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -203,6 +208,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 203 | return hm.get(key) != null; | 208 | return hm.get(key) != null; |
| 204 | } | 209 | } |
| 205 | | 210 | |
| | 211 | /// Returns any kv pair that was removed. |
| 206 | pub fn remove(hm: *Self, key: K) ?KV { | 212 | pub fn remove(hm: *Self, key: K) ?KV { |
| 207 | if (hm.entries.len == 0) return null; | 213 | if (hm.entries.len == 0) return null; |
| 208 | hm.incrementModificationCount(); | 214 | hm.incrementModificationCount(); |
| ... | @@ -236,6 +242,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -236,6 +242,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 236 | return null; | 242 | return null; |
| 237 | } | 243 | } |
| 238 | | 244 | |
| | 245 | /// Calls remove(), asserts that a kv pair is removed, and discards it. |
| | 246 | pub fn removeAssertDiscard(hm: *Self, key: K) void { |
| | 247 | assert(hm.remove(key) != null); |
| | 248 | } |
| | 249 | |
| 239 | pub fn iterator(hm: *const Self) Iterator { | 250 | pub fn iterator(hm: *const Self) Iterator { |
| 240 | return Iterator{ | 251 | return Iterator{ |
| 241 | .hm = hm, | 252 | .hm = hm, |
| ... | @@ -250,7 +261,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 | ... | @@ -250,7 +261,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 250 | try other.initCapacity(self.entries.len); | 261 | try other.initCapacity(self.entries.len); |
| 251 | var it = self.iterator(); | 262 | var it = self.iterator(); |
| 252 | while (it.next()) |entry| { | 263 | while (it.next()) |entry| { |
| 253 | assert((try other.put(entry.key, entry.value)) == null); | 264 | try other.putNoClobber(entry.key, entry.value); |
| 254 | } | 265 | } |
| 255 | return other; | 266 | return other; |
| 256 | } | 267 | } |
| ... | @@ -392,8 +403,8 @@ test "basic hash map usage" { | ... | @@ -392,8 +403,8 @@ test "basic hash map usage" { |
| 392 | testing.expect((try map.put(2, 22)) == null); | 403 | testing.expect((try map.put(2, 22)) == null); |
| 393 | testing.expect((try map.put(3, 33)) == null); | 404 | testing.expect((try map.put(3, 33)) == null); |
| 394 | testing.expect((try map.put(4, 44)) == null); | 405 | testing.expect((try map.put(4, 44)) == null); |
| 395 | testing.expect((try map.put(5, 55)) == null); | | |
| 396 | | 406 | |
| | 407 | map.putNoClobber(5, 55); |
| 397 | testing.expect((try map.put(5, 66)).?.value == 55); | 408 | testing.expect((try map.put(5, 66)).?.value == 55); |
| 398 | testing.expect((try map.put(5, 55)).?.value == 66); | 409 | testing.expect((try map.put(5, 55)).?.value == 66); |
| 399 | | 410 | |
| ... | @@ -422,6 +433,8 @@ test "basic hash map usage" { | ... | @@ -422,6 +433,8 @@ test "basic hash map usage" { |
| 422 | testing.expect(rmv1.?.value == 22); | 433 | testing.expect(rmv1.?.value == 22); |
| 423 | testing.expect(map.remove(2) == null); | 434 | testing.expect(map.remove(2) == null); |
| 424 | testing.expect(map.get(2) == null); | 435 | testing.expect(map.get(2) == null); |
| | 436 | |
| | 437 | map.removeAssertDiscard(3); |
| 425 | } | 438 | } |
| 426 | | 439 | |
| 427 | test "iterator hash map" { | 440 | test "iterator hash map" { |
| ... | @@ -431,9 +444,9 @@ test "iterator hash map" { | ... | @@ -431,9 +444,9 @@ test "iterator hash map" { |
| 431 | var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); | 444 | var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); |
| 432 | defer reset_map.deinit(); | 445 | defer reset_map.deinit(); |
| 433 | | 446 | |
| 434 | testing.expect((try reset_map.put(1, 11)) == null); | 447 | reset_map.putNoClobber(1, 11); |
| 435 | testing.expect((try reset_map.put(2, 22)) == null); | 448 | reset_map.putNoClobber(2, 22); |
| 436 | testing.expect((try reset_map.put(3, 33)) == null); | 449 | reset_map.putNoClobber(3, 33); |
| 437 | | 450 | |
| 438 | var keys = [_]i32{ | 451 | var keys = [_]i32{ |
| 439 | 3, | 452 | 3, |