authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-07 15:49:11+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-03-08 08:02:44+00:00
log17f83ace03a3bcb4f42958b43527792c186cd498
tree9d193005f50d6485b6b96fcd960e8053609e5f9a
parent229800482d28c9d55abf116cb315c78adddabe11
signaturelock-open Commit is signed but in an unrecognized format.

std.enums: remove IndexedMap, IndexedArray, IndexedSet

Searching GitHub indicated that the only use of these types in the wild is support in getty-zig, and testing for that support. This eliminates 3 more uses of usingnamespace from the standard library, and removes some unnecessarily complex generic code.

1 files changed, 715 insertions(+), 819 deletions(-)

lib/std/enums.zig+715-819
......@@ -241,957 +241,794 @@ test nameCast {
241241/// to dense indices. This type does no dynamic allocation and
242242/// can be copied by value.
243243pub fn EnumSet(comptime E: type) type {
244 const mixin = struct {
245 fn EnumSetExt(comptime Self: type) type {
246 const Indexer = Self.Indexer;
247 return struct {
248 /// Initializes the set using a struct of bools
249 pub fn init(init_values: EnumFieldStruct(E, bool, false)) Self {
250 var result = Self{};
251 comptime var i: usize = 0;
252 inline while (i < Self.len) : (i += 1) {
253 const key = comptime Indexer.keyForIndex(i);
254 const tag = comptime @tagName(key);
255 if (@field(init_values, tag)) {
256 result.bits.set(i);
257 }
258 }
259 return result;
260 }
261 };
262 }
263 };
264 return IndexedSet(EnumIndexer(E), mixin.EnumSetExt);
265}
244 return struct {
245 const Self = @This();
266246
267/// A map keyed by an enum, backed by a bitfield and a dense array.
268/// If the enum is not dense, a mapping will be constructed from
269/// enum values to dense indices. This type does no dynamic
270/// allocation and can be copied by value.
271pub fn EnumMap(comptime E: type, comptime V: type) type {
272 const mixin = struct {
273 fn EnumMapExt(comptime Self: type) type {
274 const Indexer = Self.Indexer;
275 return struct {
276 /// Initializes the map using a sparse struct of optionals
277 pub fn init(init_values: EnumFieldStruct(E, ?V, @as(?V, null))) Self {
278 var result = Self{};
279 comptime var i: usize = 0;
280 inline while (i < Self.len) : (i += 1) {
281 const key = comptime Indexer.keyForIndex(i);
282 const tag = comptime @tagName(key);
283 if (@field(init_values, tag)) |*v| {
284 result.bits.set(i);
285 result.values[i] = v.*;
286 }
287 }
288 return result;
289 }
290 /// Initializes a full mapping with all keys set to value.
291 /// Consider using EnumArray instead if the map will remain full.
292 pub fn initFull(value: V) Self {
293 var result = Self{
294 .bits = Self.BitSet.initFull(),
295 .values = undefined,
296 };
297 @memset(&result.values, value);
298 return result;
299 }
300 /// Initializes a full mapping with supplied values.
301 /// Consider using EnumArray instead if the map will remain full.
302 pub fn initFullWith(init_values: EnumFieldStruct(E, V, @as(?V, null))) Self {
303 return initFullWithDefault(@as(?V, null), init_values);
304 }
305 /// Initializes a full mapping with a provided default.
306 /// Consider using EnumArray instead if the map will remain full.
307 pub fn initFullWithDefault(comptime default: ?V, init_values: EnumFieldStruct(E, V, default)) Self {
308 var result = Self{
309 .bits = Self.BitSet.initFull(),
310 .values = undefined,
311 };
312 comptime var i: usize = 0;
313 inline while (i < Self.len) : (i += 1) {
314 const key = comptime Indexer.keyForIndex(i);
315 const tag = comptime @tagName(key);
316 result.values[i] = @field(init_values, tag);
317 }
318 return result;
319 }
320 };
321 }
322 };
323 return IndexedMap(EnumIndexer(E), V, mixin.EnumMapExt);
324}
247 /// The indexing rules for converting between keys and indices.
248 pub const Indexer = EnumIndexer(E);
249 /// The element type for this set.
250 pub const Key = Indexer.Key;
325251
326/// A multiset of enum elements up to a count of usize. Backed
327/// by an EnumArray. This type does no dynamic allocation and can
328/// be copied by value.
329pub fn EnumMultiset(comptime E: type) type {
330 return BoundedEnumMultiset(E, usize);
331}
252 const BitSet = std.StaticBitSet(Indexer.count);
332253
333/// A multiset of enum elements up to CountSize. Backed by an
334/// EnumArray. This type does no dynamic allocation and can be
335/// copied by value.
336pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
337 return struct {
338 const Self = @This();
254 /// The maximum number of items in this set.
255 pub const len = Indexer.count;
339256
340 counts: EnumArray(E, CountSize),
257 bits: BitSet = BitSet.initEmpty(),
341258
342 /// Initializes the multiset using a struct of counts.
343 pub fn init(init_counts: EnumFieldStruct(E, CountSize, 0)) Self {
344 var self = initWithCount(0);
345 inline for (@typeInfo(E).Enum.fields) |field| {
346 const c = @field(init_counts, field.name);
347 const key = @as(E, @enumFromInt(field.value));
348 self.counts.set(key, c);
259 /// Initializes the set using a struct of bools
260 pub fn init(init_values: EnumFieldStruct(E, bool, false)) Self {
261 var result: Self = .{};
262 inline for (0..Self.len) |i| {
263 const key = comptime Indexer.keyForIndex(i);
264 const tag = @tagName(key);
265 if (@field(init_values, tag)) {
266 result.bits.set(i);
267 }
349268 }
350 return self;
269 return result;
351270 }
352271
353 /// Initializes the multiset with a count of zero.
272 /// Returns a set containing no keys.
354273 pub fn initEmpty() Self {
355 return initWithCount(0);
274 return .{ .bits = BitSet.initEmpty() };
356275 }
357276
358 /// Initializes the multiset with all keys at the
359 /// same count.
360 pub fn initWithCount(comptime c: CountSize) Self {
361 return .{
362 .counts = EnumArray(E, CountSize).initDefault(c, .{}),
363 };
277 /// Returns a set containing all possible keys.
278 pub fn initFull() Self {
279 return .{ .bits = BitSet.initFull() };
364280 }
365281
366 /// Returns the total number of key counts in the multiset.
367 pub fn count(self: Self) usize {
368 var sum: usize = 0;
369 for (self.counts.values) |c| {
370 sum += c;
371 }
372 return sum;
282 /// Returns a set containing multiple keys.
283 pub fn initMany(keys: []const Key) Self {
284 var set = initEmpty();
285 for (keys) |key| set.insert(key);
286 return set;
373287 }
374288
375 /// Checks if at least one key in multiset.
376 pub fn contains(self: Self, key: E) bool {
377 return self.counts.get(key) > 0;
289 /// Returns a set containing a single key.
290 pub fn initOne(key: Key) Self {
291 return initMany(&[_]Key{key});
378292 }
379293
380 /// Removes all instance of a key from multiset. Same as
381 /// setCount(key, 0).
382 pub fn removeAll(self: *Self, key: E) void {
383 return self.counts.set(key, 0);
294 /// Returns the number of keys in the set.
295 pub fn count(self: Self) usize {
296 return self.bits.count();
384297 }
385298
386 /// Increases the key count by given amount. Caller asserts
387 /// operation will not overflow.
388 pub fn addAssertSafe(self: *Self, key: E, c: CountSize) void {
389 self.counts.getPtr(key).* += c;
299 /// Checks if a key is in the set.
300 pub fn contains(self: Self, key: Key) bool {
301 return self.bits.isSet(Indexer.indexOf(key));
390302 }
391303
392 /// Increases the key count by given amount.
393 pub fn add(self: *Self, key: E, c: CountSize) error{Overflow}!void {
394 self.counts.set(key, try std.math.add(CountSize, self.counts.get(key), c));
304 /// Puts a key in the set.
305 pub fn insert(self: *Self, key: Key) void {
306 self.bits.set(Indexer.indexOf(key));
395307 }
396308
397 /// Decreases the key count by given amount. If amount is
398 /// greater than the number of keys in multset, then key count
399 /// will be set to zero.
400 pub fn remove(self: *Self, key: E, c: CountSize) void {
401 self.counts.getPtr(key).* -= @min(self.getCount(key), c);
309 /// Removes a key from the set.
310 pub fn remove(self: *Self, key: Key) void {
311 self.bits.unset(Indexer.indexOf(key));
402312 }
403313
404 /// Returns the count for a key.
405 pub fn getCount(self: Self, key: E) CountSize {
406 return self.counts.get(key);
314 /// Changes the presence of a key in the set to match the passed bool.
315 pub fn setPresent(self: *Self, key: Key, present: bool) void {
316 self.bits.setValue(Indexer.indexOf(key), present);
407317 }
408318
409 /// Set the count for a key.
410 pub fn setCount(self: *Self, key: E, c: CountSize) void {
411 self.counts.set(key, c);
319 /// Toggles the presence of a key in the set. If the key is in
320 /// the set, removes it. Otherwise adds it.
321 pub fn toggle(self: *Self, key: Key) void {
322 self.bits.toggle(Indexer.indexOf(key));
412323 }
413324
414 /// Increases the all key counts by given multiset. Caller
415 /// asserts operation will not overflow any key.
416 pub fn addSetAssertSafe(self: *Self, other: Self) void {
417 inline for (@typeInfo(E).Enum.fields) |field| {
418 const key = @as(E, @enumFromInt(field.value));
419 self.addAssertSafe(key, other.getCount(key));
420 }
325 /// Toggles the presence of all keys in the passed set.
326 pub fn toggleSet(self: *Self, other: Self) void {
327 self.bits.toggleSet(other.bits);
421328 }
422329
423 /// Increases the all key counts by given multiset.
424 pub fn addSet(self: *Self, other: Self) error{Overflow}!void {
425 inline for (@typeInfo(E).Enum.fields) |field| {
426 const key = @as(E, @enumFromInt(field.value));
427 try self.add(key, other.getCount(key));
428 }
330 /// Toggles all possible keys in the set.
331 pub fn toggleAll(self: *Self) void {
332 self.bits.toggleAll();
429333 }
430334
431 /// Decreases the all key counts by given multiset. If
432 /// the given multiset has more key counts than this,
433 /// then that key will have a key count of zero.
434 pub fn removeSet(self: *Self, other: Self) void {
435 inline for (@typeInfo(E).Enum.fields) |field| {
436 const key = @as(E, @enumFromInt(field.value));
437 self.remove(key, other.getCount(key));
438 }
335 /// Adds all keys in the passed set to this set.
336 pub fn setUnion(self: *Self, other: Self) void {
337 self.bits.setUnion(other.bits);
439338 }
440339
441 /// Returns true iff all key counts are the same as
442 /// given multiset.
340 /// Removes all keys which are not in the passed set.
341 pub fn setIntersection(self: *Self, other: Self) void {
342 self.bits.setIntersection(other.bits);
343 }
344
345 /// Returns true iff both sets have the same keys.
443346 pub fn eql(self: Self, other: Self) bool {
444 inline for (@typeInfo(E).Enum.fields) |field| {
445 const key = @as(E, @enumFromInt(field.value));
446 if (self.getCount(key) != other.getCount(key)) {
447 return false;
448 }
449 }
450 return true;
347 return self.bits.eql(other.bits);
451348 }
452349
453 /// Returns true iff all key counts less than or
454 /// equal to the given multiset.
350 /// Returns true iff all the keys in this set are
351 /// in the other set. The other set may have keys
352 /// not found in this set.
455353 pub fn subsetOf(self: Self, other: Self) bool {
456 inline for (@typeInfo(E).Enum.fields) |field| {
457 const key = @as(E, @enumFromInt(field.value));
458 if (self.getCount(key) > other.getCount(key)) {
459 return false;
460 }
461 }
462 return true;
354 return self.bits.subsetOf(other.bits);
463355 }
464356
465 /// Returns true iff all key counts greater than or
466 /// equal to the given multiset.
357 /// Returns true iff this set contains all the keys
358 /// in the other set. This set may have keys not
359 /// found in the other set.
467360 pub fn supersetOf(self: Self, other: Self) bool {
468 inline for (@typeInfo(E).Enum.fields) |field| {
469 const key = @as(E, @enumFromInt(field.value));
470 if (self.getCount(key) < other.getCount(key)) {
471 return false;
472 }
473 }
474 return true;
361 return self.bits.supersetOf(other.bits);
475362 }
476363
477 /// Returns a multiset with the total key count of this
478 /// multiset and the other multiset. Caller asserts
479 /// operation will not overflow any key.
480 pub fn plusAssertSafe(self: Self, other: Self) Self {
481 var result = self;
482 result.addSetAssertSafe(other);
483 return result;
364 /// Returns a set with all the keys not in this set.
365 pub fn complement(self: Self) Self {
366 return .{ .bits = self.bits.complement() };
484367 }
485368
486 /// Returns a multiset with the total key count of this
487 /// multiset and the other multiset.
488 pub fn plus(self: Self, other: Self) error{Overflow}!Self {
489 var result = self;
490 try result.addSet(other);
491 return result;
369 /// Returns a set with keys that are in either this
370 /// set or the other set.
371 pub fn unionWith(self: Self, other: Self) Self {
372 return .{ .bits = self.bits.unionWith(other.bits) };
492373 }
493374
494 /// Returns a multiset with the key count of this
495 /// multiset minus the corresponding key count in the
496 /// other multiset. If the other multiset contains
497 /// more key count than this set, that key will have
498 /// a count of zero.
499 pub fn minus(self: Self, other: Self) Self {
500 var result = self;
501 result.removeSet(other);
502 return result;
375 /// Returns a set with keys that are in both this
376 /// set and the other set.
377 pub fn intersectWith(self: Self, other: Self) Self {
378 return .{ .bits = self.bits.intersectWith(other.bits) };
503379 }
504380
505 pub const Entry = EnumArray(E, CountSize).Entry;
506 pub const Iterator = EnumArray(E, CountSize).Iterator;
507
508 /// Returns an iterator over this multiset. Keys with zero
509 /// counts are included. Modifications to the set during
510 /// iteration may or may not be observed by the iterator,
511 /// but will not invalidate it.
512 pub fn iterator(self: *Self) Iterator {
513 return self.counts.iterator();
381 /// Returns a set with keys that are in either this
382 /// set or the other set, but not both.
383 pub fn xorWith(self: Self, other: Self) Self {
384 return .{ .bits = self.bits.xorWith(other.bits) };
514385 }
515 };
516}
517386
518test EnumMultiset {
519 const Ball = enum { red, green, blue };
387 /// Returns a set with keys that are in this set
388 /// except for keys in the other set.
389 pub fn differenceWith(self: Self, other: Self) Self {
390 return .{ .bits = self.bits.differenceWith(other.bits) };
391 }
520392
521 const empty = EnumMultiset(Ball).initEmpty();
522 const r0_g1_b2 = EnumMultiset(Ball).init(.{
523 .red = 0,
524 .green = 1,
525 .blue = 2,
526 });
527 const ten_of_each = EnumMultiset(Ball).initWithCount(10);
528
529 try testing.expectEqual(empty.count(), 0);
530 try testing.expectEqual(r0_g1_b2.count(), 3);
531 try testing.expectEqual(ten_of_each.count(), 30);
532
533 try testing.expect(!empty.contains(.red));
534 try testing.expect(!empty.contains(.green));
535 try testing.expect(!empty.contains(.blue));
536
537 try testing.expect(!r0_g1_b2.contains(.red));
538 try testing.expect(r0_g1_b2.contains(.green));
539 try testing.expect(r0_g1_b2.contains(.blue));
540
541 try testing.expect(ten_of_each.contains(.red));
542 try testing.expect(ten_of_each.contains(.green));
543 try testing.expect(ten_of_each.contains(.blue));
544
545 {
546 var copy = ten_of_each;
547 copy.removeAll(.red);
548 try testing.expect(!copy.contains(.red));
549
550 // removeAll second time does nothing
551 copy.removeAll(.red);
552 try testing.expect(!copy.contains(.red));
553 }
393 /// Returns an iterator over this set, which iterates in
394 /// index order. Modifications to the set during iteration
395 /// may or may not be observed by the iterator, but will
396 /// not invalidate it.
397 pub fn iterator(self: *const Self) Iterator {
398 return .{ .inner = self.bits.iterator(.{}) };
399 }
554400
555 {
556 var copy = ten_of_each;
557 copy.addAssertSafe(.red, 6);
558 try testing.expectEqual(copy.getCount(.red), 16);
559 }
401 pub const Iterator = struct {
402 inner: BitSet.Iterator(.{}),
560403
561 {
562 var copy = ten_of_each;
563 try copy.add(.red, 6);
564 try testing.expectEqual(copy.getCount(.red), 16);
404 pub fn next(self: *Iterator) ?Key {
405 return if (self.inner.next()) |index|
406 Indexer.keyForIndex(index)
407 else
408 null;
409 }
410 };
411 };
412}
565413
566 try testing.expectError(error.Overflow, copy.add(.red, std.math.maxInt(usize)));
567 }
414/// A map keyed by an enum, backed by a bitfield and a dense array.
415/// If the enum is not dense, a mapping will be constructed from
416/// enum values to dense indices. This type does no dynamic
417/// allocation and can be copied by value.
418pub fn EnumMap(comptime E: type, comptime V: type) type {
419 return struct {
420 const Self = @This();
568421
569 {
570 var copy = ten_of_each;
571 copy.remove(.red, 4);
572 try testing.expectEqual(copy.getCount(.red), 6);
422 /// The index mapping for this map
423 pub const Indexer = EnumIndexer(E);
424 /// The key type used to index this map
425 pub const Key = Indexer.Key;
426 /// The value type stored in this map
427 pub const Value = V;
428 /// The number of possible keys in the map
429 pub const len = Indexer.count;
573430
574 // subtracting more it contains does not underflow
575 copy.remove(.green, 14);
576 try testing.expectEqual(copy.getCount(.green), 0);
577 }
431 const BitSet = std.StaticBitSet(Indexer.count);
578432
579 try testing.expectEqual(empty.getCount(.green), 0);
580 try testing.expectEqual(r0_g1_b2.getCount(.green), 1);
581 try testing.expectEqual(ten_of_each.getCount(.green), 10);
433 /// Bits determining whether items are in the map
434 bits: BitSet = BitSet.initEmpty(),
435 /// Values of items in the map. If the associated
436 /// bit is zero, the value is undefined.
437 values: [Indexer.count]Value = undefined,
582438
583 {
584 var copy = empty;
585 copy.setCount(.red, 6);
586 try testing.expectEqual(copy.getCount(.red), 6);
587 }
439 /// Initializes the map using a sparse struct of optionals
440 pub fn init(init_values: EnumFieldStruct(E, ?Value, null)) Self {
441 var result: Self = .{};
442 inline for (0..Self.len) |i| {
443 const key = comptime Indexer.keyForIndex(i);
444 const tag = @tagName(key);
445 if (@field(init_values, tag)) |*v| {
446 result.bits.set(i);
447 result.values[i] = v.*;
448 }
449 }
450 }
588451
589 {
590 var copy = r0_g1_b2;
591 copy.addSetAssertSafe(ten_of_each);
592 try testing.expectEqual(copy.getCount(.red), 10);
593 try testing.expectEqual(copy.getCount(.green), 11);
594 try testing.expectEqual(copy.getCount(.blue), 12);
595 }
452 /// Initializes a full mapping with all keys set to value.
453 /// Consider using EnumArray instead if the map will remain full.
454 pub fn initFull(value: Value) Self {
455 var result: Self = .{
456 .bits = Self.BitSet.initFull(),
457 .values = undefined,
458 };
459 @memset(&result.values, value);
460 return result;
461 }
596462
597 {
598 var copy = r0_g1_b2;
599 try copy.addSet(ten_of_each);
600 try testing.expectEqual(copy.getCount(.red), 10);
601 try testing.expectEqual(copy.getCount(.green), 11);
602 try testing.expectEqual(copy.getCount(.blue), 12);
463 /// Initializes a full mapping with supplied values.
464 /// Consider using EnumArray instead if the map will remain full.
465 pub fn initFullWith(init_values: EnumFieldStruct(E, Value, null)) Self {
466 return initFullWithDefault(null, init_values);
467 }
603468
604 const full = EnumMultiset(Ball).initWithCount(std.math.maxInt(usize));
605 try testing.expectError(error.Overflow, copy.addSet(full));
606 }
469 /// Initializes a full mapping with a provided default.
470 /// Consider using EnumArray instead if the map will remain full.
471 pub fn initFullWithDefault(comptime default: ?Value, init_values: EnumFieldStruct(E, Value, default)) Self {
472 var result: Self = .{
473 .bits = Self.BitSet.initFull(),
474 .values = undefined,
475 };
476 inline for (0..Self.len) |i| {
477 const key = comptime Indexer.keyForIndex(i);
478 const tag = @tagName(key);
479 result.values[i] = @field(init_values, tag);
480 }
481 return result;
482 }
607483
608 {
609 var copy = ten_of_each;
610 copy.removeSet(r0_g1_b2);
611 try testing.expectEqual(copy.getCount(.red), 10);
612 try testing.expectEqual(copy.getCount(.green), 9);
613 try testing.expectEqual(copy.getCount(.blue), 8);
484 /// The number of items in the map.
485 pub fn count(self: Self) usize {
486 return self.bits.count();
487 }
614488
615 copy.removeSet(ten_of_each);
616 try testing.expectEqual(copy.getCount(.red), 0);
617 try testing.expectEqual(copy.getCount(.green), 0);
618 try testing.expectEqual(copy.getCount(.blue), 0);
619 }
489 /// Checks if the map contains an item.
490 pub fn contains(self: Self, key: Key) bool {
491 return self.bits.isSet(Indexer.indexOf(key));
492 }
620493
621 try testing.expect(empty.eql(empty));
622 try testing.expect(r0_g1_b2.eql(r0_g1_b2));
623 try testing.expect(ten_of_each.eql(ten_of_each));
624 try testing.expect(!empty.eql(r0_g1_b2));
625 try testing.expect(!r0_g1_b2.eql(ten_of_each));
626 try testing.expect(!ten_of_each.eql(empty));
494 /// Gets the value associated with a key.
495 /// If the key is not in the map, returns null.
496 pub fn get(self: Self, key: Key) ?Value {
497 const index = Indexer.indexOf(key);
498 return if (self.bits.isSet(index)) self.values[index] else null;
499 }
627500
628 try testing.expect(empty.subsetOf(empty));
629 try testing.expect(r0_g1_b2.subsetOf(r0_g1_b2));
630 try testing.expect(empty.subsetOf(r0_g1_b2));
631 try testing.expect(r0_g1_b2.subsetOf(ten_of_each));
632 try testing.expect(!ten_of_each.subsetOf(r0_g1_b2));
633 try testing.expect(!r0_g1_b2.subsetOf(empty));
501 /// Gets the value associated with a key, which must
502 /// exist in the map.
503 pub fn getAssertContains(self: Self, key: Key) Value {
504 const index = Indexer.indexOf(key);
505 assert(self.bits.isSet(index));
506 return self.values[index];
507 }
634508
635 try testing.expect(empty.supersetOf(empty));
636 try testing.expect(r0_g1_b2.supersetOf(r0_g1_b2));
637 try testing.expect(r0_g1_b2.supersetOf(empty));
638 try testing.expect(ten_of_each.supersetOf(r0_g1_b2));
639 try testing.expect(!r0_g1_b2.supersetOf(ten_of_each));
640 try testing.expect(!empty.supersetOf(r0_g1_b2));
509 /// Gets the address of the value associated with a key.
510 /// If the key is not in the map, returns null.
511 pub fn getPtr(self: *Self, key: Key) ?*Value {
512 const index = Indexer.indexOf(key);
513 return if (self.bits.isSet(index)) &self.values[index] else null;
514 }
641515
642 {
643 // with multisets it could be the case where two
644 // multisets are neither subset nor superset of each
645 // other.
516 /// Gets the address of the const value associated with a key.
517 /// If the key is not in the map, returns null.
518 pub fn getPtrConst(self: *const Self, key: Key) ?*const Value {
519 const index = Indexer.indexOf(key);
520 return if (self.bits.isSet(index)) &self.values[index] else null;
521 }
646522
647 const r10 = EnumMultiset(Ball).init(.{
648 .red = 10,
649 });
650 const b10 = EnumMultiset(Ball).init(.{
651 .blue = 10,
652 });
523 /// Gets the address of the value associated with a key.
524 /// The key must be present in the map.
525 pub fn getPtrAssertContains(self: *Self, key: Key) *Value {
526 const index = Indexer.indexOf(key);
527 assert(self.bits.isSet(index));
528 return &self.values[index];
529 }
653530
654 try testing.expect(!r10.subsetOf(b10));
655 try testing.expect(!b10.subsetOf(r10));
656 try testing.expect(!r10.supersetOf(b10));
657 try testing.expect(!b10.supersetOf(r10));
658 }
531 /// Gets the address of the const value associated with a key.
532 /// The key must be present in the map.
533 pub fn getPtrConstAssertContains(self: *const Self, key: Key) *const Value {
534 const index = Indexer.indexOf(key);
535 assert(self.bits.isSet(index));
536 return &self.values[index];
537 }
659538
660 {
661 const result = r0_g1_b2.plusAssertSafe(ten_of_each);
662 try testing.expectEqual(result.getCount(.red), 10);
663 try testing.expectEqual(result.getCount(.green), 11);
664 try testing.expectEqual(result.getCount(.blue), 12);
665 }
539 /// Adds the key to the map with the supplied value.
540 /// If the key is already in the map, overwrites the value.
541 pub fn put(self: *Self, key: Key, value: Value) void {
542 const index = Indexer.indexOf(key);
543 self.bits.set(index);
544 self.values[index] = value;
545 }
666546
667 {
668 const result = try r0_g1_b2.plus(ten_of_each);
669 try testing.expectEqual(result.getCount(.red), 10);
670 try testing.expectEqual(result.getCount(.green), 11);
671 try testing.expectEqual(result.getCount(.blue), 12);
547 /// Adds the key to the map with an undefined value.
548 /// If the key is already in the map, the value becomes undefined.
549 /// A pointer to the value is returned, which should be
550 /// used to initialize the value.
551 pub fn putUninitialized(self: *Self, key: Key) *Value {
552 const index = Indexer.indexOf(key);
553 self.bits.set(index);
554 self.values[index] = undefined;
555 return &self.values[index];
556 }
672557
673 const full = EnumMultiset(Ball).initWithCount(std.math.maxInt(usize));
674 try testing.expectError(error.Overflow, result.plus(full));
675 }
558 /// Sets the value associated with the key in the map,
559 /// and returns the old value. If the key was not in
560 /// the map, returns null.
561 pub fn fetchPut(self: *Self, key: Key, value: Value) ?Value {
562 const index = Indexer.indexOf(key);
563 const result: ?Value = if (self.bits.isSet(index)) self.values[index] else null;
564 self.bits.set(index);
565 self.values[index] = value;
566 return result;
567 }
676568
677 {
678 const result = ten_of_each.minus(r0_g1_b2);
679 try testing.expectEqual(result.getCount(.red), 10);
680 try testing.expectEqual(result.getCount(.green), 9);
681 try testing.expectEqual(result.getCount(.blue), 8);
682 }
569 /// Removes a key from the map. If the key was not in the map,
570 /// does nothing.
571 pub fn remove(self: *Self, key: Key) void {
572 const index = Indexer.indexOf(key);
573 self.bits.unset(index);
574 self.values[index] = undefined;
575 }
683576
684 {
685 const result = ten_of_each.minus(r0_g1_b2).minus(ten_of_each);
686 try testing.expectEqual(result.getCount(.red), 0);
687 try testing.expectEqual(result.getCount(.green), 0);
688 try testing.expectEqual(result.getCount(.blue), 0);
689 }
577 /// Removes a key from the map, and returns the old value.
578 /// If the key was not in the map, returns null.
579 pub fn fetchRemove(self: *Self, key: Key) ?Value {
580 const index = Indexer.indexOf(key);
581 const result: ?Value = if (self.bits.isSet(index)) self.values[index] else null;
582 self.bits.unset(index);
583 self.values[index] = undefined;
584 return result;
585 }
690586
691 {
692 var copy = empty;
693 var it = copy.iterator();
694 var entry = it.next().?;
695 try testing.expectEqual(entry.key, .red);
696 try testing.expectEqual(entry.value.*, 0);
697 entry = it.next().?;
698 try testing.expectEqual(entry.key, .green);
699 try testing.expectEqual(entry.value.*, 0);
700 entry = it.next().?;
701 try testing.expectEqual(entry.key, .blue);
702 try testing.expectEqual(entry.value.*, 0);
703 try testing.expectEqual(it.next(), null);
704 }
587 /// Returns an iterator over the map, which visits items in index order.
588 /// Modifications to the underlying map may or may not be observed by
589 /// the iterator, but will not invalidate it.
590 pub fn iterator(self: *Self) Iterator {
591 return .{
592 .inner = self.bits.iterator(.{}),
593 .values = &self.values,
594 };
595 }
705596
706 {
707 var copy = r0_g1_b2;
708 var it = copy.iterator();
709 var entry = it.next().?;
710 try testing.expectEqual(entry.key, .red);
711 try testing.expectEqual(entry.value.*, 0);
712 entry = it.next().?;
713 try testing.expectEqual(entry.key, .green);
714 try testing.expectEqual(entry.value.*, 1);
715 entry = it.next().?;
716 try testing.expectEqual(entry.key, .blue);
717 try testing.expectEqual(entry.value.*, 2);
718 try testing.expectEqual(it.next(), null);
719 }
720}
597 /// An entry in the map.
598 pub const Entry = struct {
599 /// The key associated with this entry.
600 /// Modifying this key will not change the map.
601 key: Key,
721602
722/// An array keyed by an enum, backed by a dense array.
723/// If the enum is not dense, a mapping will be constructed from
724/// enum values to dense indices. This type does no dynamic
725/// allocation and can be copied by value.
726pub fn EnumArray(comptime E: type, comptime V: type) type {
727 const mixin = struct {
728 fn EnumArrayExt(comptime Self: type) type {
729 const Indexer = Self.Indexer;
730 return struct {
731 /// Initializes all values in the enum array
732 pub fn init(init_values: EnumFieldStruct(E, V, @as(?V, null))) Self {
733 return initDefault(@as(?V, null), init_values);
734 }
603 /// A pointer to the value in the map associated
604 /// with this key. Modifications through this
605 /// pointer will modify the underlying data.
606 value: *Value,
607 };
608
609 pub const Iterator = struct {
610 inner: BitSet.Iterator(.{}),
611 values: *[Indexer.count]Value,
735612
736 /// Initializes values in the enum array, with the specified default.
737 pub fn initDefault(comptime default: ?V, init_values: EnumFieldStruct(E, V, default)) Self {
738 var result = Self{ .values = undefined };
739 comptime var i: usize = 0;
740 inline while (i < Self.len) : (i += 1) {
741 const key = comptime Indexer.keyForIndex(i);
742 const tag = @tagName(key);
743 result.values[i] = @field(init_values, tag);
613 pub fn next(self: *Iterator) ?Entry {
614 return if (self.inner.next()) |index|
615 Entry{
616 .key = Indexer.keyForIndex(index),
617 .value = &self.values[index],
744618 }
745 return result;
746 }
747 };
748 }
619 else
620 null;
621 }
622 };
749623 };
750 return IndexedArray(EnumIndexer(E), V, mixin.EnumArrayExt);
751624}
752625
753fn NoExtension(comptime Self: type) type {
754 _ = Self;
755 return NoExt;
626/// A multiset of enum elements up to a count of usize. Backed
627/// by an EnumArray. This type does no dynamic allocation and can
628/// be copied by value.
629pub fn EnumMultiset(comptime E: type) type {
630 return BoundedEnumMultiset(E, usize);
756631}
757const NoExt = struct {};
758632
759/// A set type with an Indexer mapping from keys to indices.
760/// Presence or absence is stored as a dense bitfield. This
761/// type does no allocation and can be copied by value.
762pub fn IndexedSet(comptime I: type, comptime Ext: ?fn (type) type) type {
763 comptime ensureIndexer(I);
633/// A multiset of enum elements up to CountSize. Backed by an
634/// EnumArray. This type does no dynamic allocation and can be
635/// copied by value.
636pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
764637 return struct {
765638 const Self = @This();
766639
767 pub usingnamespace (Ext orelse NoExtension)(Self);
768
769 /// The indexing rules for converting between keys and indices.
770 pub const Indexer = I;
771 /// The element type for this set.
772 pub const Key = Indexer.Key;
773
774 const BitSet = std.StaticBitSet(Indexer.count);
775
776 /// The maximum number of items in this set.
777 pub const len = Indexer.count;
778
779 bits: BitSet = BitSet.initEmpty(),
640 counts: EnumArray(E, CountSize),
780641
781 /// Returns a set containing no keys.
782 pub fn initEmpty() Self {
783 return .{ .bits = BitSet.initEmpty() };
642 /// Initializes the multiset using a struct of counts.
643 pub fn init(init_counts: EnumFieldStruct(E, CountSize, 0)) Self {
644 var self = initWithCount(0);
645 inline for (@typeInfo(E).Enum.fields) |field| {
646 const c = @field(init_counts, field.name);
647 const key = @as(E, @enumFromInt(field.value));
648 self.counts.set(key, c);
649 }
650 return self;
784651 }
785652
786 /// Returns a set containing all possible keys.
787 pub fn initFull() Self {
788 return .{ .bits = BitSet.initFull() };
653 /// Initializes the multiset with a count of zero.
654 pub fn initEmpty() Self {
655 return initWithCount(0);
789656 }
790657
791 /// Returns a set containing multiple keys.
792 pub fn initMany(keys: []const Key) Self {
793 var set = initEmpty();
794 for (keys) |key| set.insert(key);
795 return set;
658 /// Initializes the multiset with all keys at the
659 /// same count.
660 pub fn initWithCount(comptime c: CountSize) Self {
661 return .{
662 .counts = EnumArray(E, CountSize).initDefault(c, .{}),
663 };
796664 }
797665
798 /// Returns a set containing a single key.
799 pub fn initOne(key: Key) Self {
800 return initMany(&[_]Key{key});
666 /// Returns the total number of key counts in the multiset.
667 pub fn count(self: Self) usize {
668 var sum: usize = 0;
669 for (self.counts.values) |c| {
670 sum += c;
671 }
672 return sum;
801673 }
802674
803 /// Returns the number of keys in the set.
804 pub fn count(self: Self) usize {
805 return self.bits.count();
675 /// Checks if at least one key in multiset.
676 pub fn contains(self: Self, key: E) bool {
677 return self.counts.get(key) > 0;
806678 }
807679
808 /// Checks if a key is in the set.
809 pub fn contains(self: Self, key: Key) bool {
810 return self.bits.isSet(Indexer.indexOf(key));
680 /// Removes all instance of a key from multiset. Same as
681 /// setCount(key, 0).
682 pub fn removeAll(self: *Self, key: E) void {
683 return self.counts.set(key, 0);
811684 }
812685
813 /// Puts a key in the set.
814 pub fn insert(self: *Self, key: Key) void {
815 self.bits.set(Indexer.indexOf(key));
686 /// Increases the key count by given amount. Caller asserts
687 /// operation will not overflow.
688 pub fn addAssertSafe(self: *Self, key: E, c: CountSize) void {
689 self.counts.getPtr(key).* += c;
816690 }
817691
818 /// Removes a key from the set.
819 pub fn remove(self: *Self, key: Key) void {
820 self.bits.unset(Indexer.indexOf(key));
692 /// Increases the key count by given amount.
693 pub fn add(self: *Self, key: E, c: CountSize) error{Overflow}!void {
694 self.counts.set(key, try std.math.add(CountSize, self.counts.get(key), c));
821695 }
822696
823 /// Changes the presence of a key in the set to match the passed bool.
824 pub fn setPresent(self: *Self, key: Key, present: bool) void {
825 self.bits.setValue(Indexer.indexOf(key), present);
697 /// Decreases the key count by given amount. If amount is
698 /// greater than the number of keys in multset, then key count
699 /// will be set to zero.
700 pub fn remove(self: *Self, key: E, c: CountSize) void {
701 self.counts.getPtr(key).* -= @min(self.getCount(key), c);
826702 }
827703
828 /// Toggles the presence of a key in the set. If the key is in
829 /// the set, removes it. Otherwise adds it.
830 pub fn toggle(self: *Self, key: Key) void {
831 self.bits.toggle(Indexer.indexOf(key));
704 /// Returns the count for a key.
705 pub fn getCount(self: Self, key: E) CountSize {
706 return self.counts.get(key);
832707 }
833708
834 /// Toggles the presence of all keys in the passed set.
835 pub fn toggleSet(self: *Self, other: Self) void {
836 self.bits.toggleSet(other.bits);
709 /// Set the count for a key.
710 pub fn setCount(self: *Self, key: E, c: CountSize) void {
711 self.counts.set(key, c);
837712 }
838713
839 /// Toggles all possible keys in the set.
840 pub fn toggleAll(self: *Self) void {
841 self.bits.toggleAll();
714 /// Increases the all key counts by given multiset. Caller
715 /// asserts operation will not overflow any key.
716 pub fn addSetAssertSafe(self: *Self, other: Self) void {
717 inline for (@typeInfo(E).Enum.fields) |field| {
718 const key = @as(E, @enumFromInt(field.value));
719 self.addAssertSafe(key, other.getCount(key));
720 }
842721 }
843722
844 /// Adds all keys in the passed set to this set.
845 pub fn setUnion(self: *Self, other: Self) void {
846 self.bits.setUnion(other.bits);
723 /// Increases the all key counts by given multiset.
724 pub fn addSet(self: *Self, other: Self) error{Overflow}!void {
725 inline for (@typeInfo(E).Enum.fields) |field| {
726 const key = @as(E, @enumFromInt(field.value));
727 try self.add(key, other.getCount(key));
728 }
847729 }
848730
849 /// Removes all keys which are not in the passed set.
850 pub fn setIntersection(self: *Self, other: Self) void {
851 self.bits.setIntersection(other.bits);
731 /// Decreases the all key counts by given multiset. If
732 /// the given multiset has more key counts than this,
733 /// then that key will have a key count of zero.
734 pub fn removeSet(self: *Self, other: Self) void {
735 inline for (@typeInfo(E).Enum.fields) |field| {
736 const key = @as(E, @enumFromInt(field.value));
737 self.remove(key, other.getCount(key));
738 }
852739 }
853740
854 /// Returns true iff both sets have the same keys.
741 /// Returns true iff all key counts are the same as
742 /// given multiset.
855743 pub fn eql(self: Self, other: Self) bool {
856 return self.bits.eql(other.bits);
744 inline for (@typeInfo(E).Enum.fields) |field| {
745 const key = @as(E, @enumFromInt(field.value));
746 if (self.getCount(key) != other.getCount(key)) {
747 return false;
748 }
749 }
750 return true;
857751 }
858752
859 /// Returns true iff all the keys in this set are
860 /// in the other set. The other set may have keys
861 /// not found in this set.
753 /// Returns true iff all key counts less than or
754 /// equal to the given multiset.
862755 pub fn subsetOf(self: Self, other: Self) bool {
863 return self.bits.subsetOf(other.bits);
756 inline for (@typeInfo(E).Enum.fields) |field| {
757 const key = @as(E, @enumFromInt(field.value));
758 if (self.getCount(key) > other.getCount(key)) {
759 return false;
760 }
761 }
762 return true;
864763 }
865764
866 /// Returns true iff this set contains all the keys
867 /// in the other set. This set may have keys not
868 /// found in the other set.
765 /// Returns true iff all key counts greater than or
766 /// equal to the given multiset.
869767 pub fn supersetOf(self: Self, other: Self) bool {
870 return self.bits.supersetOf(other.bits);
871 }
872
873 /// Returns a set with all the keys not in this set.
874 pub fn complement(self: Self) Self {
875 return .{ .bits = self.bits.complement() };
876 }
877
878 /// Returns a set with keys that are in either this
879 /// set or the other set.
880 pub fn unionWith(self: Self, other: Self) Self {
881 return .{ .bits = self.bits.unionWith(other.bits) };
882 }
883
884 /// Returns a set with keys that are in both this
885 /// set and the other set.
886 pub fn intersectWith(self: Self, other: Self) Self {
887 return .{ .bits = self.bits.intersectWith(other.bits) };
768 inline for (@typeInfo(E).Enum.fields) |field| {
769 const key = @as(E, @enumFromInt(field.value));
770 if (self.getCount(key) < other.getCount(key)) {
771 return false;
772 }
773 }
774 return true;
888775 }
889776
890 /// Returns a set with keys that are in either this
891 /// set or the other set, but not both.
892 pub fn xorWith(self: Self, other: Self) Self {
893 return .{ .bits = self.bits.xorWith(other.bits) };
777 /// Returns a multiset with the total key count of this
778 /// multiset and the other multiset. Caller asserts
779 /// operation will not overflow any key.
780 pub fn plusAssertSafe(self: Self, other: Self) Self {
781 var result = self;
782 result.addSetAssertSafe(other);
783 return result;
894784 }
895785
896 /// Returns a set with keys that are in this set
897 /// except for keys in the other set.
898 pub fn differenceWith(self: Self, other: Self) Self {
899 return .{ .bits = self.bits.differenceWith(other.bits) };
786 /// Returns a multiset with the total key count of this
787 /// multiset and the other multiset.
788 pub fn plus(self: Self, other: Self) error{Overflow}!Self {
789 var result = self;
790 try result.addSet(other);
791 return result;
900792 }
901793
902 /// Returns an iterator over this set, which iterates in
903 /// index order. Modifications to the set during iteration
904 /// may or may not be observed by the iterator, but will
905 /// not invalidate it.
906 pub fn iterator(self: *const Self) Iterator {
907 return .{ .inner = self.bits.iterator(.{}) };
794 /// Returns a multiset with the key count of this
795 /// multiset minus the corresponding key count in the
796 /// other multiset. If the other multiset contains
797 /// more key count than this set, that key will have
798 /// a count of zero.
799 pub fn minus(self: Self, other: Self) Self {
800 var result = self;
801 result.removeSet(other);
802 return result;
908803 }
909804
910 pub const Iterator = struct {
911 inner: BitSet.Iterator(.{}),
805 pub const Entry = EnumArray(E, CountSize).Entry;
806 pub const Iterator = EnumArray(E, CountSize).Iterator;
912807
913 pub fn next(self: *Iterator) ?Key {
914 return if (self.inner.next()) |index|
915 Indexer.keyForIndex(index)
916 else
917 null;
918 }
919 };
808 /// Returns an iterator over this multiset. Keys with zero
809 /// counts are included. Modifications to the set during
810 /// iteration may or may not be observed by the iterator,
811 /// but will not invalidate it.
812 pub fn iterator(self: *Self) Iterator {
813 return self.counts.iterator();
814 }
920815 };
921816}
922817
923test "pure EnumSet fns" {
924 const Suit = enum { spades, hearts, clubs, diamonds };
925
926 const empty = EnumSet(Suit).initEmpty();
927 const full = EnumSet(Suit).initFull();
928 const black = EnumSet(Suit).initMany(&[_]Suit{ .spades, .clubs });
929 const red = EnumSet(Suit).initMany(&[_]Suit{ .hearts, .diamonds });
930
931 try testing.expect(empty.eql(empty));
932 try testing.expect(full.eql(full));
933 try testing.expect(!empty.eql(full));
934 try testing.expect(!full.eql(empty));
935 try testing.expect(!empty.eql(black));
936 try testing.expect(!full.eql(red));
937 try testing.expect(!red.eql(empty));
938 try testing.expect(!black.eql(full));
939
940 try testing.expect(empty.subsetOf(empty));
941 try testing.expect(empty.subsetOf(full));
942 try testing.expect(full.subsetOf(full));
943 try testing.expect(!black.subsetOf(red));
944 try testing.expect(!red.subsetOf(black));
945
946 try testing.expect(full.supersetOf(full));
947 try testing.expect(full.supersetOf(empty));
948 try testing.expect(empty.supersetOf(empty));
949 try testing.expect(!black.supersetOf(red));
950 try testing.expect(!red.supersetOf(black));
951
952 try testing.expect(empty.complement().eql(full));
953 try testing.expect(full.complement().eql(empty));
954 try testing.expect(black.complement().eql(red));
955 try testing.expect(red.complement().eql(black));
818test EnumMultiset {
819 const Ball = enum { red, green, blue };
956820
957 try testing.expect(empty.unionWith(empty).eql(empty));
958 try testing.expect(empty.unionWith(full).eql(full));
959 try testing.expect(full.unionWith(full).eql(full));
960 try testing.expect(full.unionWith(empty).eql(full));
961 try testing.expect(black.unionWith(red).eql(full));
962 try testing.expect(red.unionWith(black).eql(full));
821 const empty = EnumMultiset(Ball).initEmpty();
822 const r0_g1_b2 = EnumMultiset(Ball).init(.{
823 .red = 0,
824 .green = 1,
825 .blue = 2,
826 });
827 const ten_of_each = EnumMultiset(Ball).initWithCount(10);
963828
964 try testing.expect(empty.intersectWith(empty).eql(empty));
965 try testing.expect(empty.intersectWith(full).eql(empty));
966 try testing.expect(full.intersectWith(full).eql(full));
967 try testing.expect(full.intersectWith(empty).eql(empty));
968 try testing.expect(black.intersectWith(red).eql(empty));
969 try testing.expect(red.intersectWith(black).eql(empty));
829 try testing.expectEqual(empty.count(), 0);
830 try testing.expectEqual(r0_g1_b2.count(), 3);
831 try testing.expectEqual(ten_of_each.count(), 30);
970832
971 try testing.expect(empty.xorWith(empty).eql(empty));
972 try testing.expect(empty.xorWith(full).eql(full));
973 try testing.expect(full.xorWith(full).eql(empty));
974 try testing.expect(full.xorWith(empty).eql(full));
975 try testing.expect(black.xorWith(red).eql(full));
976 try testing.expect(red.xorWith(black).eql(full));
833 try testing.expect(!empty.contains(.red));
834 try testing.expect(!empty.contains(.green));
835 try testing.expect(!empty.contains(.blue));
977836
978 try testing.expect(empty.differenceWith(empty).eql(empty));
979 try testing.expect(empty.differenceWith(full).eql(empty));
980 try testing.expect(full.differenceWith(full).eql(empty));
981 try testing.expect(full.differenceWith(empty).eql(full));
982 try testing.expect(full.differenceWith(red).eql(black));
983 try testing.expect(full.differenceWith(black).eql(red));
984}
837 try testing.expect(!r0_g1_b2.contains(.red));
838 try testing.expect(r0_g1_b2.contains(.green));
839 try testing.expect(r0_g1_b2.contains(.blue));
985840
986test "EnumSet empty" {
987 const E = enum {};
988 const empty = EnumSet(E).initEmpty();
989 const full = EnumSet(E).initFull();
841 try testing.expect(ten_of_each.contains(.red));
842 try testing.expect(ten_of_each.contains(.green));
843 try testing.expect(ten_of_each.contains(.blue));
990844
991 try std.testing.expect(empty.eql(full));
992 try std.testing.expect(empty.complement().eql(full));
993 try std.testing.expect(empty.complement().eql(full.complement()));
994 try std.testing.expect(empty.eql(full.complement()));
995}
845 {
846 var copy = ten_of_each;
847 copy.removeAll(.red);
848 try testing.expect(!copy.contains(.red));
996849
997test "EnumSet const iterator" {
998 const Direction = enum { up, down, left, right };
999 const diag_move = init: {
1000 var move = EnumSet(Direction).initEmpty();
1001 move.insert(.right);
1002 move.insert(.up);
1003 break :init move;
1004 };
850 // removeAll second time does nothing
851 copy.removeAll(.red);
852 try testing.expect(!copy.contains(.red));
853 }
1005854
1006 var result = EnumSet(Direction).initEmpty();
1007 var it = diag_move.iterator();
1008 while (it.next()) |dir| {
1009 result.insert(dir);
855 {
856 var copy = ten_of_each;
857 copy.addAssertSafe(.red, 6);
858 try testing.expectEqual(copy.getCount(.red), 16);
1010859 }
1011860
1012 try testing.expect(result.eql(diag_move));
1013}
861 {
862 var copy = ten_of_each;
863 try copy.add(.red, 6);
864 try testing.expectEqual(copy.getCount(.red), 16);
1014865
1015/// A map from keys to values, using an index lookup. Uses a
1016/// bitfield to track presence and a dense array of values.
1017/// This type does no allocation and can be copied by value.
1018pub fn IndexedMap(comptime I: type, comptime V: type, comptime Ext: ?fn (type) type) type {
1019 comptime ensureIndexer(I);
1020 return struct {
1021 const Self = @This();
866 try testing.expectError(error.Overflow, copy.add(.red, std.math.maxInt(usize)));
867 }
1022868
1023 pub usingnamespace (Ext orelse NoExtension)(Self);
869 {
870 var copy = ten_of_each;
871 copy.remove(.red, 4);
872 try testing.expectEqual(copy.getCount(.red), 6);
1024873
1025 /// The index mapping for this map
1026 pub const Indexer = I;
1027 /// The key type used to index this map
1028 pub const Key = Indexer.Key;
1029 /// The value type stored in this map
1030 pub const Value = V;
1031 /// The number of possible keys in the map
1032 pub const len = Indexer.count;
874 // subtracting more it contains does not underflow
875 copy.remove(.green, 14);
876 try testing.expectEqual(copy.getCount(.green), 0);
877 }
1033878
1034 const BitSet = std.StaticBitSet(Indexer.count);
879 try testing.expectEqual(empty.getCount(.green), 0);
880 try testing.expectEqual(r0_g1_b2.getCount(.green), 1);
881 try testing.expectEqual(ten_of_each.getCount(.green), 10);
1035882
1036 /// Bits determining whether items are in the map
1037 bits: BitSet = BitSet.initEmpty(),
1038 /// Values of items in the map. If the associated
1039 /// bit is zero, the value is undefined.
1040 values: [Indexer.count]Value = undefined,
883 {
884 var copy = empty;
885 copy.setCount(.red, 6);
886 try testing.expectEqual(copy.getCount(.red), 6);
887 }
1041888
1042 /// The number of items in the map.
1043 pub fn count(self: Self) usize {
1044 return self.bits.count();
1045 }
889 {
890 var copy = r0_g1_b2;
891 copy.addSetAssertSafe(ten_of_each);
892 try testing.expectEqual(copy.getCount(.red), 10);
893 try testing.expectEqual(copy.getCount(.green), 11);
894 try testing.expectEqual(copy.getCount(.blue), 12);
895 }
1046896
1047 /// Checks if the map contains an item.
1048 pub fn contains(self: Self, key: Key) bool {
1049 return self.bits.isSet(Indexer.indexOf(key));
1050 }
897 {
898 var copy = r0_g1_b2;
899 try copy.addSet(ten_of_each);
900 try testing.expectEqual(copy.getCount(.red), 10);
901 try testing.expectEqual(copy.getCount(.green), 11);
902 try testing.expectEqual(copy.getCount(.blue), 12);
1051903
1052 /// Gets the value associated with a key.
1053 /// If the key is not in the map, returns null.
1054 pub fn get(self: Self, key: Key) ?Value {
1055 const index = Indexer.indexOf(key);
1056 return if (self.bits.isSet(index)) self.values[index] else null;
1057 }
904 const full = EnumMultiset(Ball).initWithCount(std.math.maxInt(usize));
905 try testing.expectError(error.Overflow, copy.addSet(full));
906 }
1058907
1059 /// Gets the value associated with a key, which must
1060 /// exist in the map.
1061 pub fn getAssertContains(self: Self, key: Key) Value {
1062 const index = Indexer.indexOf(key);
1063 assert(self.bits.isSet(index));
1064 return self.values[index];
1065 }
908 {
909 var copy = ten_of_each;
910 copy.removeSet(r0_g1_b2);
911 try testing.expectEqual(copy.getCount(.red), 10);
912 try testing.expectEqual(copy.getCount(.green), 9);
913 try testing.expectEqual(copy.getCount(.blue), 8);
1066914
1067 /// Gets the address of the value associated with a key.
1068 /// If the key is not in the map, returns null.
1069 pub fn getPtr(self: *Self, key: Key) ?*Value {
1070 const index = Indexer.indexOf(key);
1071 return if (self.bits.isSet(index)) &self.values[index] else null;
1072 }
915 copy.removeSet(ten_of_each);
916 try testing.expectEqual(copy.getCount(.red), 0);
917 try testing.expectEqual(copy.getCount(.green), 0);
918 try testing.expectEqual(copy.getCount(.blue), 0);
919 }
1073920
1074 /// Gets the address of the const value associated with a key.
1075 /// If the key is not in the map, returns null.
1076 pub fn getPtrConst(self: *const Self, key: Key) ?*const Value {
1077 const index = Indexer.indexOf(key);
1078 return if (self.bits.isSet(index)) &self.values[index] else null;
1079 }
921 try testing.expect(empty.eql(empty));
922 try testing.expect(r0_g1_b2.eql(r0_g1_b2));
923 try testing.expect(ten_of_each.eql(ten_of_each));
924 try testing.expect(!empty.eql(r0_g1_b2));
925 try testing.expect(!r0_g1_b2.eql(ten_of_each));
926 try testing.expect(!ten_of_each.eql(empty));
1080927
1081 /// Gets the address of the value associated with a key.
1082 /// The key must be present in the map.
1083 pub fn getPtrAssertContains(self: *Self, key: Key) *Value {
1084 const index = Indexer.indexOf(key);
1085 assert(self.bits.isSet(index));
1086 return &self.values[index];
1087 }
928 try testing.expect(empty.subsetOf(empty));
929 try testing.expect(r0_g1_b2.subsetOf(r0_g1_b2));
930 try testing.expect(empty.subsetOf(r0_g1_b2));
931 try testing.expect(r0_g1_b2.subsetOf(ten_of_each));
932 try testing.expect(!ten_of_each.subsetOf(r0_g1_b2));
933 try testing.expect(!r0_g1_b2.subsetOf(empty));
1088934
1089 /// Gets the address of the const value associated with a key.
1090 /// The key must be present in the map.
1091 pub fn getPtrConstAssertContains(self: *const Self, key: Key) *const Value {
1092 const index = Indexer.indexOf(key);
1093 assert(self.bits.isSet(index));
1094 return &self.values[index];
1095 }
935 try testing.expect(empty.supersetOf(empty));
936 try testing.expect(r0_g1_b2.supersetOf(r0_g1_b2));
937 try testing.expect(r0_g1_b2.supersetOf(empty));
938 try testing.expect(ten_of_each.supersetOf(r0_g1_b2));
939 try testing.expect(!r0_g1_b2.supersetOf(ten_of_each));
940 try testing.expect(!empty.supersetOf(r0_g1_b2));
1096941
1097 /// Adds the key to the map with the supplied value.
1098 /// If the key is already in the map, overwrites the value.
1099 pub fn put(self: *Self, key: Key, value: Value) void {
1100 const index = Indexer.indexOf(key);
1101 self.bits.set(index);
1102 self.values[index] = value;
1103 }
942 {
943 // with multisets it could be the case where two
944 // multisets are neither subset nor superset of each
945 // other.
1104946
1105 /// Adds the key to the map with an undefined value.
1106 /// If the key is already in the map, the value becomes undefined.
1107 /// A pointer to the value is returned, which should be
1108 /// used to initialize the value.
1109 pub fn putUninitialized(self: *Self, key: Key) *Value {
1110 const index = Indexer.indexOf(key);
1111 self.bits.set(index);
1112 self.values[index] = undefined;
1113 return &self.values[index];
1114 }
947 const r10 = EnumMultiset(Ball).init(.{
948 .red = 10,
949 });
950 const b10 = EnumMultiset(Ball).init(.{
951 .blue = 10,
952 });
1115953
1116 /// Sets the value associated with the key in the map,
1117 /// and returns the old value. If the key was not in
1118 /// the map, returns null.
1119 pub fn fetchPut(self: *Self, key: Key, value: Value) ?Value {
1120 const index = Indexer.indexOf(key);
1121 const result: ?Value = if (self.bits.isSet(index)) self.values[index] else null;
1122 self.bits.set(index);
1123 self.values[index] = value;
1124 return result;
1125 }
954 try testing.expect(!r10.subsetOf(b10));
955 try testing.expect(!b10.subsetOf(r10));
956 try testing.expect(!r10.supersetOf(b10));
957 try testing.expect(!b10.supersetOf(r10));
958 }
1126959
1127 /// Removes a key from the map. If the key was not in the map,
1128 /// does nothing.
1129 pub fn remove(self: *Self, key: Key) void {
1130 const index = Indexer.indexOf(key);
1131 self.bits.unset(index);
1132 self.values[index] = undefined;
1133 }
960 {
961 const result = r0_g1_b2.plusAssertSafe(ten_of_each);
962 try testing.expectEqual(result.getCount(.red), 10);
963 try testing.expectEqual(result.getCount(.green), 11);
964 try testing.expectEqual(result.getCount(.blue), 12);
965 }
1134966
1135 /// Removes a key from the map, and returns the old value.
1136 /// If the key was not in the map, returns null.
1137 pub fn fetchRemove(self: *Self, key: Key) ?Value {
1138 const index = Indexer.indexOf(key);
1139 const result: ?Value = if (self.bits.isSet(index)) self.values[index] else null;
1140 self.bits.unset(index);
1141 self.values[index] = undefined;
1142 return result;
1143 }
967 {
968 const result = try r0_g1_b2.plus(ten_of_each);
969 try testing.expectEqual(result.getCount(.red), 10);
970 try testing.expectEqual(result.getCount(.green), 11);
971 try testing.expectEqual(result.getCount(.blue), 12);
1144972
1145 /// Returns an iterator over the map, which visits items in index order.
1146 /// Modifications to the underlying map may or may not be observed by
1147 /// the iterator, but will not invalidate it.
1148 pub fn iterator(self: *Self) Iterator {
1149 return .{
1150 .inner = self.bits.iterator(.{}),
1151 .values = &self.values,
1152 };
1153 }
973 const full = EnumMultiset(Ball).initWithCount(std.math.maxInt(usize));
974 try testing.expectError(error.Overflow, result.plus(full));
975 }
1154976
1155 /// An entry in the map.
1156 pub const Entry = struct {
1157 /// The key associated with this entry.
1158 /// Modifying this key will not change the map.
1159 key: Key,
977 {
978 const result = ten_of_each.minus(r0_g1_b2);
979 try testing.expectEqual(result.getCount(.red), 10);
980 try testing.expectEqual(result.getCount(.green), 9);
981 try testing.expectEqual(result.getCount(.blue), 8);
982 }
1160983
1161 /// A pointer to the value in the map associated
1162 /// with this key. Modifications through this
1163 /// pointer will modify the underlying data.
1164 value: *Value,
1165 };
984 {
985 const result = ten_of_each.minus(r0_g1_b2).minus(ten_of_each);
986 try testing.expectEqual(result.getCount(.red), 0);
987 try testing.expectEqual(result.getCount(.green), 0);
988 try testing.expectEqual(result.getCount(.blue), 0);
989 }
1166990
1167 pub const Iterator = struct {
1168 inner: BitSet.Iterator(.{}),
1169 values: *[Indexer.count]Value,
991 {
992 var copy = empty;
993 var it = copy.iterator();
994 var entry = it.next().?;
995 try testing.expectEqual(entry.key, .red);
996 try testing.expectEqual(entry.value.*, 0);
997 entry = it.next().?;
998 try testing.expectEqual(entry.key, .green);
999 try testing.expectEqual(entry.value.*, 0);
1000 entry = it.next().?;
1001 try testing.expectEqual(entry.key, .blue);
1002 try testing.expectEqual(entry.value.*, 0);
1003 try testing.expectEqual(it.next(), null);
1004 }
11701005
1171 pub fn next(self: *Iterator) ?Entry {
1172 return if (self.inner.next()) |index|
1173 Entry{
1174 .key = Indexer.keyForIndex(index),
1175 .value = &self.values[index],
1176 }
1177 else
1178 null;
1179 }
1180 };
1181 };
1006 {
1007 var copy = r0_g1_b2;
1008 var it = copy.iterator();
1009 var entry = it.next().?;
1010 try testing.expectEqual(entry.key, .red);
1011 try testing.expectEqual(entry.value.*, 0);
1012 entry = it.next().?;
1013 try testing.expectEqual(entry.key, .green);
1014 try testing.expectEqual(entry.value.*, 1);
1015 entry = it.next().?;
1016 try testing.expectEqual(entry.key, .blue);
1017 try testing.expectEqual(entry.value.*, 2);
1018 try testing.expectEqual(it.next(), null);
1019 }
11821020}
11831021
1184/// A dense array of values, using an indexed lookup.
1185/// This type does no allocation and can be copied by value.
1186pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: ?fn (type) type) type {
1187 comptime ensureIndexer(I);
1022/// An array keyed by an enum, backed by a dense array.
1023/// If the enum is not dense, a mapping will be constructed from
1024/// enum values to dense indices. This type does no dynamic
1025/// allocation and can be copied by value.
1026pub fn EnumArray(comptime E: type, comptime V: type) type {
11881027 return struct {
11891028 const Self = @This();
11901029
1191 pub usingnamespace (Ext orelse NoExtension)(Self);
1192
11931030 /// The index mapping for this map
1194 pub const Indexer = I;
1031 pub const Indexer = EnumIndexer(E);
11951032 /// The key type used to index this map
11961033 pub const Key = Indexer.Key;
11971034 /// The value type stored in this map
......@@ -1201,6 +1038,21 @@ pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: ?fn (type)
12011038
12021039 values: [Indexer.count]Value,
12031040
1041 pub fn init(init_values: EnumFieldStruct(E, Value, null)) Self {
1042 return initDefault(null, init_values);
1043 }
1044
1045 /// Initializes values in the enum array, with the specified default.
1046 pub fn initDefault(comptime default: ?Value, init_values: EnumFieldStruct(E, Value, default)) Self {
1047 var result: Self = .{ .values = undefined };
1048 inline for (0..Self.len) |i| {
1049 const key = comptime Indexer.keyForIndex(i);
1050 const tag = @tagName(key);
1051 result.values[i] = @field(init_values, tag);
1052 }
1053 return result;
1054 }
1055
12041056 pub fn initUndefined() Self {
12051057 return Self{ .values = undefined };
12061058 }
......@@ -1269,46 +1121,96 @@ pub fn IndexedArray(comptime I: type, comptime V: type, comptime Ext: ?fn (type)
12691121 };
12701122}
12711123
1272/// Verifies that a type is a valid Indexer, providing a helpful
1273/// compile error if not. An Indexer maps a comptime-known set
1274/// of keys to a dense set of zero-based indices.
1275/// The indexer interface must look like this:
1276/// ```
1277/// struct {
1278/// /// The key type which this indexer converts to indices
1279/// pub const Key: type,
1280/// /// The number of indexes in the dense mapping
1281/// pub const count: comptime_int,
1282/// /// Converts from a key to an index
1283/// pub fn indexOf(Key) usize;
1284/// /// Converts from an index to a key
1285/// pub fn keyForIndex(usize) Key;
1286/// }
1287/// ```
1288pub fn ensureIndexer(comptime T: type) void {
1289 comptime {
1290 if (!@hasDecl(T, "Key")) @compileError("Indexer must have decl Key: type.");
1291 if (@TypeOf(T.Key) != type) @compileError("Indexer.Key must be a type.");
1292 if (!@hasDecl(T, "count")) @compileError("Indexer must have decl count: comptime_int.");
1293 if (@TypeOf(T.count) != comptime_int) @compileError("Indexer.count must be a comptime_int.");
1294 if (!@hasDecl(T, "indexOf")) @compileError("Indexer.indexOf must be a fn (Key) usize.");
1295 if (@TypeOf(T.indexOf) != fn (T.Key) usize) @compileError("Indexer must have decl indexOf: fn (Key) usize.");
1296 if (!@hasDecl(T, "keyForIndex")) @compileError("Indexer must have decl keyForIndex: fn (usize) Key.");
1297 if (@TypeOf(T.keyForIndex) != fn (usize) T.Key) @compileError("Indexer.keyForIndex must be a fn (usize) Key.");
1298 }
1124test "pure EnumSet fns" {
1125 const Suit = enum { spades, hearts, clubs, diamonds };
1126
1127 const empty = EnumSet(Suit).initEmpty();
1128 const full = EnumSet(Suit).initFull();
1129 const black = EnumSet(Suit).initMany(&[_]Suit{ .spades, .clubs });
1130 const red = EnumSet(Suit).initMany(&[_]Suit{ .hearts, .diamonds });
1131
1132 try testing.expect(empty.eql(empty));
1133 try testing.expect(full.eql(full));
1134 try testing.expect(!empty.eql(full));
1135 try testing.expect(!full.eql(empty));
1136 try testing.expect(!empty.eql(black));
1137 try testing.expect(!full.eql(red));
1138 try testing.expect(!red.eql(empty));
1139 try testing.expect(!black.eql(full));
1140
1141 try testing.expect(empty.subsetOf(empty));
1142 try testing.expect(empty.subsetOf(full));
1143 try testing.expect(full.subsetOf(full));
1144 try testing.expect(!black.subsetOf(red));
1145 try testing.expect(!red.subsetOf(black));
1146
1147 try testing.expect(full.supersetOf(full));
1148 try testing.expect(full.supersetOf(empty));
1149 try testing.expect(empty.supersetOf(empty));
1150 try testing.expect(!black.supersetOf(red));
1151 try testing.expect(!red.supersetOf(black));
1152
1153 try testing.expect(empty.complement().eql(full));
1154 try testing.expect(full.complement().eql(empty));
1155 try testing.expect(black.complement().eql(red));
1156 try testing.expect(red.complement().eql(black));
1157
1158 try testing.expect(empty.unionWith(empty).eql(empty));
1159 try testing.expect(empty.unionWith(full).eql(full));
1160 try testing.expect(full.unionWith(full).eql(full));
1161 try testing.expect(full.unionWith(empty).eql(full));
1162 try testing.expect(black.unionWith(red).eql(full));
1163 try testing.expect(red.unionWith(black).eql(full));
1164
1165 try testing.expect(empty.intersectWith(empty).eql(empty));
1166 try testing.expect(empty.intersectWith(full).eql(empty));
1167 try testing.expect(full.intersectWith(full).eql(full));
1168 try testing.expect(full.intersectWith(empty).eql(empty));
1169 try testing.expect(black.intersectWith(red).eql(empty));
1170 try testing.expect(red.intersectWith(black).eql(empty));
1171
1172 try testing.expect(empty.xorWith(empty).eql(empty));
1173 try testing.expect(empty.xorWith(full).eql(full));
1174 try testing.expect(full.xorWith(full).eql(empty));
1175 try testing.expect(full.xorWith(empty).eql(full));
1176 try testing.expect(black.xorWith(red).eql(full));
1177 try testing.expect(red.xorWith(black).eql(full));
1178
1179 try testing.expect(empty.differenceWith(empty).eql(empty));
1180 try testing.expect(empty.differenceWith(full).eql(empty));
1181 try testing.expect(full.differenceWith(full).eql(empty));
1182 try testing.expect(full.differenceWith(empty).eql(full));
1183 try testing.expect(full.differenceWith(red).eql(black));
1184 try testing.expect(full.differenceWith(black).eql(red));
12991185}
13001186
1301test ensureIndexer {
1302 ensureIndexer(struct {
1303 pub const Key = u32;
1304 pub const count: comptime_int = 8;
1305 pub fn indexOf(k: Key) usize {
1306 return @as(usize, @intCast(k));
1307 }
1308 pub fn keyForIndex(index: usize) Key {
1309 return @as(Key, @intCast(index));
1310 }
1311 });
1187test "EnumSet empty" {
1188 const E = enum {};
1189 const empty = EnumSet(E).initEmpty();
1190 const full = EnumSet(E).initFull();
1191
1192 try std.testing.expect(empty.eql(full));
1193 try std.testing.expect(empty.complement().eql(full));
1194 try std.testing.expect(empty.complement().eql(full.complement()));
1195 try std.testing.expect(empty.eql(full.complement()));
1196}
1197
1198test "EnumSet const iterator" {
1199 const Direction = enum { up, down, left, right };
1200 const diag_move = init: {
1201 var move = EnumSet(Direction).initEmpty();
1202 move.insert(.right);
1203 move.insert(.up);
1204 break :init move;
1205 };
1206
1207 var result = EnumSet(Direction).initEmpty();
1208 var it = diag_move.iterator();
1209 while (it.next()) |dir| {
1210 result.insert(dir);
1211 }
1212
1213 try testing.expect(result.eql(diag_move));
13121214}
13131215
13141216pub fn EnumIndexer(comptime E: type) type {
......@@ -1438,7 +1340,6 @@ test "EnumIndexer non-exhaustive" {
14381340 _,
14391341 };
14401342 const Indexer = EnumIndexer(E);
1441 ensureIndexer(Indexer);
14421343
14431344 const min_tag: E = @enumFromInt(std.math.minInt(BackingInt));
14441345 const max_tag: E = @enumFromInt(std.math.maxInt(BackingInt));
......@@ -1466,7 +1367,6 @@ test "EnumIndexer non-exhaustive" {
14661367test "EnumIndexer dense zeroed" {
14671368 const E = enum(u2) { b = 1, a = 0, c = 2 };
14681369 const Indexer = EnumIndexer(E);
1469 ensureIndexer(Indexer);
14701370 try testing.expectEqual(E, Indexer.Key);
14711371 try testing.expectEqual(3, Indexer.count);
14721372
......@@ -1482,7 +1382,6 @@ test "EnumIndexer dense zeroed" {
14821382test "EnumIndexer dense positive" {
14831383 const E = enum(u4) { c = 6, a = 4, b = 5 };
14841384 const Indexer = EnumIndexer(E);
1485 ensureIndexer(Indexer);
14861385 try testing.expectEqual(E, Indexer.Key);
14871386 try testing.expectEqual(3, Indexer.count);
14881387
......@@ -1498,7 +1397,6 @@ test "EnumIndexer dense positive" {
14981397test "EnumIndexer dense negative" {
14991398 const E = enum(i4) { a = -6, c = -4, b = -5 };
15001399 const Indexer = EnumIndexer(E);
1501 ensureIndexer(Indexer);
15021400 try testing.expectEqual(E, Indexer.Key);
15031401 try testing.expectEqual(3, Indexer.count);
15041402
......@@ -1514,7 +1412,6 @@ test "EnumIndexer dense negative" {
15141412test "EnumIndexer sparse" {
15151413 const E = enum(i4) { a = -2, c = 6, b = 4 };
15161414 const Indexer = EnumIndexer(E);
1517 ensureIndexer(Indexer);
15181415 try testing.expectEqual(E, Indexer.Key);
15191416 try testing.expectEqual(3, Indexer.count);
15201417
......@@ -1530,7 +1427,6 @@ test "EnumIndexer sparse" {
15301427test "EnumIndexer empty" {
15311428 const E = enum {};
15321429 const Indexer = EnumIndexer(E);
1533 ensureIndexer(Indexer);
15341430 try testing.expectEqual(E, Indexer.Key);
15351431 try testing.expectEqual(0, Indexer.count);
15361432}