| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | //! This module contains utilities and data structures for working with enums. | 1 | //! This module contains utilities and data structures for working with enums. |
| 2 | | 2 | |
| 3 | const std = @import("std.zig"); | 3 | const std = @import("std"); |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| 6 | const EnumField = std.builtin.Type.EnumField; | 6 | const EnumField = std.builtin.Type.EnumField; |
| ... | @@ -369,6 +369,11 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { | ... | @@ -369,6 +369,11 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { |
| 369 | | 369 | |
| 370 | bits: BitSet = BitSet.initEmpty(), | 370 | bits: BitSet = BitSet.initEmpty(), |
| 371 | | 371 | |
| | 372 | /// Returns a set containing no keys. |
| | 373 | pub fn initEmpty() Self { |
| | 374 | return .{ .bits = BitSet.initEmpty() }; |
| | 375 | } |
| | 376 | |
| 372 | /// Returns a set containing all possible keys. | 377 | /// Returns a set containing all possible keys. |
| 373 | pub fn initFull() Self { | 378 | pub fn initFull() Self { |
| 374 | return .{ .bits = BitSet.initFull() }; | 379 | return .{ .bits = BitSet.initFull() }; |
| ... | @@ -425,6 +430,54 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { | ... | @@ -425,6 +430,54 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { |
| 425 | self.bits.setIntersection(other.bits); | 430 | self.bits.setIntersection(other.bits); |
| 426 | } | 431 | } |
| 427 | | 432 | |
| | 433 | /// Returns true iff both sets have the same keys. |
| | 434 | pub fn eql(self: Self, other: Self) bool { |
| | 435 | return self.bits.eql(other.bits); |
| | 436 | } |
| | 437 | |
| | 438 | /// Returns true iff all the keys in this set are |
| | 439 | /// in the other set. The other set may have keys |
| | 440 | /// not found in this set. |
| | 441 | pub fn subsetOf(self: Self, other: Self) bool { |
| | 442 | return self.bits.subsetOf(other.bits); |
| | 443 | } |
| | 444 | |
| | 445 | /// Returns true iff this set contains all the keys |
| | 446 | /// in the other set. This set may have keys not |
| | 447 | /// found in the other set. |
| | 448 | pub fn supersetOf(self: Self, other: Self) bool { |
| | 449 | return self.bits.supersetOf(other.bits); |
| | 450 | } |
| | 451 | |
| | 452 | /// Returns a set with all the keys not in this set. |
| | 453 | pub fn complement(self: Self) Self { |
| | 454 | return .{ .bits = self.bits.complement() }; |
| | 455 | } |
| | 456 | |
| | 457 | /// Returns a set with keys that are in either this |
| | 458 | /// set or the other set. |
| | 459 | pub fn unionWith(self: Self, other: Self) Self { |
| | 460 | return .{ .bits = self.bits.unionWith(other.bits) }; |
| | 461 | } |
| | 462 | |
| | 463 | /// Returns a set with keys that are in both this |
| | 464 | /// set and the other set. |
| | 465 | pub fn intersectWith(self: Self, other: Self) Self { |
| | 466 | return .{ .bits = self.bits.intersectWith(other.bits) }; |
| | 467 | } |
| | 468 | |
| | 469 | /// Returns a set with keys that are in either this |
| | 470 | /// set or the other set, but not both. |
| | 471 | pub fn xorWith(self: Self, other: Self) Self { |
| | 472 | return .{ .bits = self.bits.xorWith(other.bits) }; |
| | 473 | } |
| | 474 | |
| | 475 | /// Returns a set with keys that are in this set |
| | 476 | /// except for keys in the other set. |
| | 477 | pub fn differenceWith(self: Self, other: Self) Self { |
| | 478 | return .{ .bits = self.bits.differenceWith(other.bits) }; |
| | 479 | } |
| | 480 | |
| 428 | /// Returns an iterator over this set, which iterates in | 481 | /// Returns an iterator over this set, which iterates in |
| 429 | /// index order. Modifications to the set during iteration | 482 | /// index order. Modifications to the set during iteration |
| 430 | /// may or may not be observed by the iterator, but will | 483 | /// may or may not be observed by the iterator, but will |
| ... | @@ -446,6 +499,81 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { | ... | @@ -446,6 +499,81 @@ pub fn IndexedSet(comptime I: type, comptime Ext: fn (type) type) type { |
| 446 | }; | 499 | }; |
| 447 | } | 500 | } |
| 448 | | 501 | |
| | 502 | test "pure EnumSet fns" { |
| | 503 | const Suit = enum { spades, hearts, clubs, diamonds }; |
| | 504 | |
| | 505 | const empty = EnumSet(Suit).initEmpty(); |
| | 506 | const full = EnumSet(Suit).initFull(); |
| | 507 | |
| | 508 | const black = black: { |
| | 509 | var set = EnumSet(Suit).initEmpty(); |
| | 510 | set.insert(.spades); |
| | 511 | set.insert(.clubs); |
| | 512 | break :black set; |
| | 513 | }; |
| | 514 | |
| | 515 | const red = red: { |
| | 516 | var set = EnumSet(Suit).initEmpty(); |
| | 517 | set.insert(.hearts); |
| | 518 | set.insert(.diamonds); |
| | 519 | break :red set; |
| | 520 | }; |
| | 521 | |
| | 522 | try testing.expect(empty.eql(empty)); |
| | 523 | try testing.expect(full.eql(full)); |
| | 524 | try testing.expect(!empty.eql(full)); |
| | 525 | try testing.expect(!full.eql(empty)); |
| | 526 | try testing.expect(!empty.eql(black)); |
| | 527 | try testing.expect(!full.eql(red)); |
| | 528 | try testing.expect(!red.eql(empty)); |
| | 529 | try testing.expect(!black.eql(full)); |
| | 530 | |
| | 531 | try testing.expect(empty.subsetOf(empty)); |
| | 532 | try testing.expect(empty.subsetOf(full)); |
| | 533 | try testing.expect(full.subsetOf(full)); |
| | 534 | try testing.expect(!black.subsetOf(red)); |
| | 535 | try testing.expect(!red.subsetOf(black)); |
| | 536 | |
| | 537 | try testing.expect(full.supersetOf(full)); |
| | 538 | try testing.expect(full.supersetOf(empty)); |
| | 539 | try testing.expect(empty.supersetOf(empty)); |
| | 540 | try testing.expect(!black.supersetOf(red)); |
| | 541 | try testing.expect(!red.supersetOf(black)); |
| | 542 | |
| | 543 | try testing.expect(empty.complement().eql(full)); |
| | 544 | try testing.expect(full.complement().eql(empty)); |
| | 545 | try testing.expect(black.complement().eql(red)); |
| | 546 | try testing.expect(red.complement().eql(black)); |
| | 547 | |
| | 548 | try testing.expect(empty.unionWith(empty).eql(empty)); |
| | 549 | try testing.expect(empty.unionWith(full).eql(full)); |
| | 550 | try testing.expect(full.unionWith(full).eql(full)); |
| | 551 | try testing.expect(full.unionWith(empty).eql(full)); |
| | 552 | try testing.expect(black.unionWith(red).eql(full)); |
| | 553 | try testing.expect(red.unionWith(black).eql(full)); |
| | 554 | |
| | 555 | try testing.expect(empty.intersectWith(empty).eql(empty)); |
| | 556 | try testing.expect(empty.intersectWith(full).eql(empty)); |
| | 557 | try testing.expect(full.intersectWith(full).eql(full)); |
| | 558 | try testing.expect(full.intersectWith(empty).eql(empty)); |
| | 559 | try testing.expect(black.intersectWith(red).eql(empty)); |
| | 560 | try testing.expect(red.intersectWith(black).eql(empty)); |
| | 561 | |
| | 562 | try testing.expect(empty.xorWith(empty).eql(empty)); |
| | 563 | try testing.expect(empty.xorWith(full).eql(full)); |
| | 564 | try testing.expect(full.xorWith(full).eql(empty)); |
| | 565 | try testing.expect(full.xorWith(empty).eql(full)); |
| | 566 | try testing.expect(black.xorWith(red).eql(full)); |
| | 567 | try testing.expect(red.xorWith(black).eql(full)); |
| | 568 | |
| | 569 | try testing.expect(empty.differenceWith(empty).eql(empty)); |
| | 570 | try testing.expect(empty.differenceWith(full).eql(empty)); |
| | 571 | try testing.expect(full.differenceWith(full).eql(empty)); |
| | 572 | try testing.expect(full.differenceWith(empty).eql(full)); |
| | 573 | try testing.expect(full.differenceWith(red).eql(black)); |
| | 574 | try testing.expect(full.differenceWith(black).eql(red)); |
| | 575 | } |
| | 576 | |
| 449 | /// A map from keys to values, using an index lookup. Uses a | 577 | /// A map from keys to values, using an index lookup. Uses a |
| 450 | /// bitfield to track presence and a dense array of values. | 578 | /// bitfield to track presence and a dense array of values. |
| 451 | /// This type does no allocation and can be copied by value. | 579 | /// This type does no allocation and can be copied by value. |