Commit fb4cb430e0
Changed files (1)
lib
std
lib/std/enums.zig
@@ -18,7 +18,7 @@ const EnumField = std.builtin.TypeInfo.EnumField;
pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type {
const StructField = std.builtin.TypeInfo.StructField;
var fields: []const StructField = &[_]StructField{};
- for (uniqueFields(E)) |field, i| {
+ for (std.meta.fields(E)) |field, i| {
fields = fields ++ &[_]StructField{.{
.name = field.name,
.field_type = Data,
@@ -48,72 +48,12 @@ pub fn valuesFromFields(comptime E: type, comptime fields: []const EnumField) []
}
}
-test "std.enums.valuesFromFields" {
- const E = extern enum { a, b, c, d = 0 };
- const fields = valuesFromFields(E, &[_]EnumField{
- .{ .name = "b", .value = undefined },
- .{ .name = "a", .value = undefined },
- .{ .name = "a", .value = undefined },
- .{ .name = "d", .value = undefined },
- });
- testing.expectEqual(E.b, fields[0]);
- testing.expectEqual(E.a, fields[1]);
- testing.expectEqual(E.d, fields[2]); // a == d
- testing.expectEqual(E.d, fields[3]);
-}
-
/// Returns the set of all named values in the given enum, in
/// declaration order.
pub fn values(comptime E: type) []const E {
return comptime valuesFromFields(E, @typeInfo(E).Enum.fields);
}
-test "std.enum.values" {
- const E = extern enum { a, b, c, d = 0 };
- testing.expectEqualSlices(E, &.{ .a, .b, .c, .d }, values(E));
-}
-
-/// Returns the set of all unique named values in the given enum, in
-/// declaration order. For repeated values in extern enums, only the
-/// first name for each value is included.
-pub fn uniqueValues(comptime E: type) []const E {
- return comptime valuesFromFields(E, uniqueFields(E));
-}
-
-test "std.enum.uniqueValues" {
- const E = extern enum { a, b, c, d = 0, e, f = 3 };
- testing.expectEqualSlices(E, &.{ .a, .b, .c, .f }, uniqueValues(E));
-
- const F = enum { a, b, c };
- testing.expectEqualSlices(F, &.{ .a, .b, .c }, uniqueValues(F));
-}
-
-/// Returns the set of all unique field values in the given enum, in
-/// declaration order. For repeated values in extern enums, only the
-/// first name for each value is included.
-pub fn uniqueFields(comptime E: type) []const EnumField {
- comptime {
- const info = @typeInfo(E).Enum;
- const raw_fields = info.fields;
- // Only extern enums can contain duplicates,
- // so fast path other types.
- if (info.layout != .Extern) {
- return raw_fields;
- }
-
- var unique_fields: []const EnumField = &[_]EnumField{};
- outer: for (raw_fields) |candidate| {
- for (unique_fields) |u| {
- if (u.value == candidate.value)
- continue :outer;
- }
- unique_fields = unique_fields ++ &[_]EnumField{candidate};
- }
-
- return unique_fields;
- }
-}
-
/// Determines the length of a direct-mapped enum array, indexed by
/// @intCast(usize, @enumToInt(enum_value)).
/// If the enum is non-exhaustive, the resulting length will only be enough
@@ -126,7 +66,7 @@ pub fn uniqueFields(comptime E: type) []const EnumField {
fn directEnumArrayLen(comptime E: type, comptime max_unused_slots: comptime_int) comptime_int {
var max_value: comptime_int = -1;
const max_usize: comptime_int = ~@as(usize, 0);
- const fields = uniqueFields(E);
+ const fields = std.meta.fields(E);
for (fields) |f| {
if (f.value < 0) {
@compileError("Cannot create a direct enum array for " ++ @typeName(E) ++ ", field ." ++ f.name ++ " has a negative value.");
@@ -248,8 +188,8 @@ pub fn nameCast(comptime E: type, comptime value: anytype) E {
}
test "std.enums.nameCast" {
- const A = enum { a = 0, b = 1 };
- const B = enum { a = 1, b = 0 };
+ const A = enum(u1) { a = 0, b = 1 };
+ const B = enum(u1) { a = 1, b = 0 };
testing.expectEqual(A.a, nameCast(A, .a));
testing.expectEqual(A.a, nameCast(A, A.a));
testing.expectEqual(A.a, nameCast(A, B.a));
@@ -796,7 +736,7 @@ pub fn EnumIndexer(comptime E: type) type {
@compileError("Cannot create an enum indexer for a non-exhaustive enum.");
}
- const const_fields = uniqueFields(E);
+ const const_fields = std.meta.fields(E);
var fields = const_fields[0..const_fields.len].*;
if (fields.len == 0) {
return struct {
@@ -848,7 +788,7 @@ pub fn EnumIndexer(comptime E: type) type {
}
test "std.enums.EnumIndexer dense zeroed" {
- const E = enum { b = 1, a = 0, c = 2 };
+ const E = enum(u2) { b = 1, a = 0, c = 2 };
const Indexer = EnumIndexer(E);
ensureIndexer(Indexer);
testing.expectEqual(E, Indexer.Key);
@@ -910,379 +850,3 @@ test "std.enums.EnumIndexer sparse" {
testing.expectEqual(E.b, Indexer.keyForIndex(1));
testing.expectEqual(E.c, Indexer.keyForIndex(2));
}
-
-test "std.enums.EnumIndexer repeats" {
- const E = extern enum { a = -2, c = 6, b = 4, b2 = 4 };
- const Indexer = EnumIndexer(E);
- ensureIndexer(Indexer);
- testing.expectEqual(E, Indexer.Key);
- testing.expectEqual(@as(usize, 3), Indexer.count);
-
- testing.expectEqual(@as(usize, 0), Indexer.indexOf(.a));
- testing.expectEqual(@as(usize, 1), Indexer.indexOf(.b));
- testing.expectEqual(@as(usize, 2), Indexer.indexOf(.c));
-
- testing.expectEqual(E.a, Indexer.keyForIndex(0));
- testing.expectEqual(E.b, Indexer.keyForIndex(1));
- testing.expectEqual(E.c, Indexer.keyForIndex(2));
-}
-
-test "std.enums.EnumSet" {
- const E = extern enum { a, b, c, d, e = 0 };
- const Set = EnumSet(E);
- testing.expectEqual(E, Set.Key);
- testing.expectEqual(EnumIndexer(E), Set.Indexer);
- testing.expectEqual(@as(usize, 4), Set.len);
-
- // Empty sets
- const empty = Set{};
- comptime testing.expect(empty.count() == 0);
-
- var empty_b = Set.init(.{});
- testing.expect(empty_b.count() == 0);
-
- const empty_c = comptime Set.init(.{});
- comptime testing.expect(empty_c.count() == 0);
-
- const full = Set.initFull();
- testing.expect(full.count() == Set.len);
-
- const full_b = comptime Set.initFull();
- comptime testing.expect(full_b.count() == Set.len);
-
- testing.expectEqual(false, empty.contains(.a));
- testing.expectEqual(false, empty.contains(.b));
- testing.expectEqual(false, empty.contains(.c));
- testing.expectEqual(false, empty.contains(.d));
- testing.expectEqual(false, empty.contains(.e));
- {
- var iter = empty_b.iterator();
- testing.expectEqual(@as(?E, null), iter.next());
- }
-
- var mut = Set.init(.{
- .a = true,
- .c = true,
- });
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(false, mut.contains(.b));
- testing.expectEqual(true, mut.contains(.c));
- testing.expectEqual(false, mut.contains(.d));
- testing.expectEqual(true, mut.contains(.e)); // aliases a
- {
- var it = mut.iterator();
- testing.expectEqual(@as(?E, .a), it.next());
- testing.expectEqual(@as(?E, .c), it.next());
- testing.expectEqual(@as(?E, null), it.next());
- }
-
- mut.toggleAll();
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(false, mut.contains(.a));
- testing.expectEqual(true, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(true, mut.contains(.d));
- testing.expectEqual(false, mut.contains(.e)); // aliases a
- {
- var it = mut.iterator();
- testing.expectEqual(@as(?E, .b), it.next());
- testing.expectEqual(@as(?E, .d), it.next());
- testing.expectEqual(@as(?E, null), it.next());
- }
-
- mut.toggleSet(Set.init(.{ .a = true, .b = true }));
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(false, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(true, mut.contains(.d));
- testing.expectEqual(true, mut.contains(.e)); // aliases a
-
- mut.setUnion(Set.init(.{ .a = true, .b = true }));
- testing.expectEqual(@as(usize, 3), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(true, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(true, mut.contains(.d));
-
- mut.remove(.c);
- mut.remove(.b);
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(false, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(true, mut.contains(.d));
-
- mut.setIntersection(Set.init(.{ .a = true, .b = true }));
- testing.expectEqual(@as(usize, 1), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(false, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(false, mut.contains(.d));
-
- mut.insert(.a);
- mut.insert(.b);
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(true, mut.contains(.a));
- testing.expectEqual(true, mut.contains(.b));
- testing.expectEqual(false, mut.contains(.c));
- testing.expectEqual(false, mut.contains(.d));
-
- mut.setPresent(.a, false);
- mut.toggle(.b);
- mut.toggle(.c);
- mut.setPresent(.d, true);
- testing.expectEqual(@as(usize, 2), mut.count());
- testing.expectEqual(false, mut.contains(.a));
- testing.expectEqual(false, mut.contains(.b));
- testing.expectEqual(true, mut.contains(.c));
- testing.expectEqual(true, mut.contains(.d));
-}
-
-test "std.enums.EnumArray void" {
- const E = extern enum { a, b, c, d, e = 0 };
- const ArrayVoid = EnumArray(E, void);
- testing.expectEqual(E, ArrayVoid.Key);
- testing.expectEqual(EnumIndexer(E), ArrayVoid.Indexer);
- testing.expectEqual(void, ArrayVoid.Value);
- testing.expectEqual(@as(usize, 4), ArrayVoid.len);
-
- const undef = ArrayVoid.initUndefined();
- var inst = ArrayVoid.initFill({});
- const inst2 = ArrayVoid.init(.{ .a = {}, .b = {}, .c = {}, .d = {} });
- const inst3 = ArrayVoid.initDefault({}, .{});
-
- _ = inst.get(.a);
- _ = inst.getPtr(.b);
- _ = inst.getPtrConst(.c);
- inst.set(.a, {});
-
- var it = inst.iterator();
- testing.expectEqual(E.a, it.next().?.key);
- testing.expectEqual(E.b, it.next().?.key);
- testing.expectEqual(E.c, it.next().?.key);
- testing.expectEqual(E.d, it.next().?.key);
- testing.expect(it.next() == null);
-}
-
-test "std.enums.EnumArray sized" {
- const E = extern enum { a, b, c, d, e = 0 };
- const Array = EnumArray(E, usize);
- testing.expectEqual(E, Array.Key);
- testing.expectEqual(EnumIndexer(E), Array.Indexer);
- testing.expectEqual(usize, Array.Value);
- testing.expectEqual(@as(usize, 4), Array.len);
-
- const undef = Array.initUndefined();
- var inst = Array.initFill(5);
- const inst2 = Array.init(.{ .a = 1, .b = 2, .c = 3, .d = 4 });
- const inst3 = Array.initDefault(6, .{ .b = 4, .c = 2 });
-
- testing.expectEqual(@as(usize, 5), inst.get(.a));
- testing.expectEqual(@as(usize, 5), inst.get(.b));
- testing.expectEqual(@as(usize, 5), inst.get(.c));
- testing.expectEqual(@as(usize, 5), inst.get(.d));
-
- testing.expectEqual(@as(usize, 1), inst2.get(.a));
- testing.expectEqual(@as(usize, 2), inst2.get(.b));
- testing.expectEqual(@as(usize, 3), inst2.get(.c));
- testing.expectEqual(@as(usize, 4), inst2.get(.d));
-
- testing.expectEqual(@as(usize, 6), inst3.get(.a));
- testing.expectEqual(@as(usize, 4), inst3.get(.b));
- testing.expectEqual(@as(usize, 2), inst3.get(.c));
- testing.expectEqual(@as(usize, 6), inst3.get(.d));
-
- testing.expectEqual(&inst.values[0], inst.getPtr(.a));
- testing.expectEqual(&inst.values[1], inst.getPtr(.b));
- testing.expectEqual(&inst.values[2], inst.getPtr(.c));
- testing.expectEqual(&inst.values[3], inst.getPtr(.d));
-
- testing.expectEqual(@as(*const usize, &inst.values[0]), inst.getPtrConst(.a));
- testing.expectEqual(@as(*const usize, &inst.values[1]), inst.getPtrConst(.b));
- testing.expectEqual(@as(*const usize, &inst.values[2]), inst.getPtrConst(.c));
- testing.expectEqual(@as(*const usize, &inst.values[3]), inst.getPtrConst(.d));
-
- inst.set(.c, 8);
- testing.expectEqual(@as(usize, 5), inst.get(.a));
- testing.expectEqual(@as(usize, 5), inst.get(.b));
- testing.expectEqual(@as(usize, 8), inst.get(.c));
- testing.expectEqual(@as(usize, 5), inst.get(.d));
-
- var it = inst.iterator();
- const Entry = Array.Entry;
- testing.expectEqual(@as(?Entry, Entry{
- .key = .a,
- .value = &inst.values[0],
- }), it.next());
- testing.expectEqual(@as(?Entry, Entry{
- .key = .b,
- .value = &inst.values[1],
- }), it.next());
- testing.expectEqual(@as(?Entry, Entry{
- .key = .c,
- .value = &inst.values[2],
- }), it.next());
- testing.expectEqual(@as(?Entry, Entry{
- .key = .d,
- .value = &inst.values[3],
- }), it.next());
- testing.expectEqual(@as(?Entry, null), it.next());
-}
-
-test "std.enums.EnumMap void" {
- const E = extern enum { a, b, c, d, e = 0 };
- const Map = EnumMap(E, void);
- testing.expectEqual(E, Map.Key);
- testing.expectEqual(EnumIndexer(E), Map.Indexer);
- testing.expectEqual(void, Map.Value);
- testing.expectEqual(@as(usize, 4), Map.len);
-
- const b = Map.initFull({});
- testing.expectEqual(@as(usize, 4), b.count());
-
- const c = Map.initFullWith(.{ .a = {}, .b = {}, .c = {}, .d = {} });
- testing.expectEqual(@as(usize, 4), c.count());
-
- const d = Map.initFullWithDefault({}, .{ .b = {} });
- testing.expectEqual(@as(usize, 4), d.count());
-
- var a = Map.init(.{ .b = {}, .d = {} });
- testing.expectEqual(@as(usize, 2), a.count());
- testing.expectEqual(false, a.contains(.a));
- testing.expectEqual(true, a.contains(.b));
- testing.expectEqual(false, a.contains(.c));
- testing.expectEqual(true, a.contains(.d));
- testing.expect(a.get(.a) == null);
- testing.expect(a.get(.b) != null);
- testing.expect(a.get(.c) == null);
- testing.expect(a.get(.d) != null);
- testing.expect(a.getPtr(.a) == null);
- testing.expect(a.getPtr(.b) != null);
- testing.expect(a.getPtr(.c) == null);
- testing.expect(a.getPtr(.d) != null);
- testing.expect(a.getPtrConst(.a) == null);
- testing.expect(a.getPtrConst(.b) != null);
- testing.expect(a.getPtrConst(.c) == null);
- testing.expect(a.getPtrConst(.d) != null);
- _ = a.getPtrAssertContains(.b);
- _ = a.getAssertContains(.d);
-
- a.put(.a, {});
- a.put(.a, {});
- a.putUninitialized(.c).* = {};
- a.putUninitialized(.c).* = {};
-
- testing.expectEqual(@as(usize, 4), a.count());
- testing.expect(a.get(.a) != null);
- testing.expect(a.get(.b) != null);
- testing.expect(a.get(.c) != null);
- testing.expect(a.get(.d) != null);
-
- a.remove(.a);
- _ = a.fetchRemove(.c);
-
- var iter = a.iterator();
- const Entry = Map.Entry;
- testing.expectEqual(E.b, iter.next().?.key);
- testing.expectEqual(E.d, iter.next().?.key);
- testing.expect(iter.next() == null);
-}
-
-test "std.enums.EnumMap sized" {
- const E = extern enum { a, b, c, d, e = 0 };
- const Map = EnumMap(E, usize);
- testing.expectEqual(E, Map.Key);
- testing.expectEqual(EnumIndexer(E), Map.Indexer);
- testing.expectEqual(usize, Map.Value);
- testing.expectEqual(@as(usize, 4), Map.len);
-
- const b = Map.initFull(5);
- testing.expectEqual(@as(usize, 4), b.count());
- testing.expect(b.contains(.a));
- testing.expect(b.contains(.b));
- testing.expect(b.contains(.c));
- testing.expect(b.contains(.d));
- testing.expectEqual(@as(?usize, 5), b.get(.a));
- testing.expectEqual(@as(?usize, 5), b.get(.b));
- testing.expectEqual(@as(?usize, 5), b.get(.c));
- testing.expectEqual(@as(?usize, 5), b.get(.d));
-
- const c = Map.initFullWith(.{ .a = 1, .b = 2, .c = 3, .d = 4 });
- testing.expectEqual(@as(usize, 4), c.count());
- testing.expect(c.contains(.a));
- testing.expect(c.contains(.b));
- testing.expect(c.contains(.c));
- testing.expect(c.contains(.d));
- testing.expectEqual(@as(?usize, 1), c.get(.a));
- testing.expectEqual(@as(?usize, 2), c.get(.b));
- testing.expectEqual(@as(?usize, 3), c.get(.c));
- testing.expectEqual(@as(?usize, 4), c.get(.d));
-
- const d = Map.initFullWithDefault(6, .{ .b = 2, .c = 4 });
- testing.expectEqual(@as(usize, 4), d.count());
- testing.expect(d.contains(.a));
- testing.expect(d.contains(.b));
- testing.expect(d.contains(.c));
- testing.expect(d.contains(.d));
- testing.expectEqual(@as(?usize, 6), d.get(.a));
- testing.expectEqual(@as(?usize, 2), d.get(.b));
- testing.expectEqual(@as(?usize, 4), d.get(.c));
- testing.expectEqual(@as(?usize, 6), d.get(.d));
-
- var a = Map.init(.{ .b = 2, .d = 4 });
- testing.expectEqual(@as(usize, 2), a.count());
- testing.expectEqual(false, a.contains(.a));
- testing.expectEqual(true, a.contains(.b));
- testing.expectEqual(false, a.contains(.c));
- testing.expectEqual(true, a.contains(.d));
-
- testing.expectEqual(@as(?usize, null), a.get(.a));
- testing.expectEqual(@as(?usize, 2), a.get(.b));
- testing.expectEqual(@as(?usize, null), a.get(.c));
- testing.expectEqual(@as(?usize, 4), a.get(.d));
-
- testing.expectEqual(@as(?*usize, null), a.getPtr(.a));
- testing.expectEqual(@as(?*usize, &a.values[1]), a.getPtr(.b));
- testing.expectEqual(@as(?*usize, null), a.getPtr(.c));
- testing.expectEqual(@as(?*usize, &a.values[3]), a.getPtr(.d));
-
- testing.expectEqual(@as(?*const usize, null), a.getPtrConst(.a));
- testing.expectEqual(@as(?*const usize, &a.values[1]), a.getPtrConst(.b));
- testing.expectEqual(@as(?*const usize, null), a.getPtrConst(.c));
- testing.expectEqual(@as(?*const usize, &a.values[3]), a.getPtrConst(.d));
-
- testing.expectEqual(@as(*const usize, &a.values[1]), a.getPtrAssertContains(.b));
- testing.expectEqual(@as(*const usize, &a.values[3]), a.getPtrAssertContains(.d));
- testing.expectEqual(@as(usize, 2), a.getAssertContains(.b));
- testing.expectEqual(@as(usize, 4), a.getAssertContains(.d));
-
- a.put(.a, 3);
- a.put(.a, 5);
- a.putUninitialized(.c).* = 7;
- a.putUninitialized(.c).* = 9;
-
- testing.expectEqual(@as(usize, 4), a.count());
- testing.expectEqual(@as(?usize, 5), a.get(.a));
- testing.expectEqual(@as(?usize, 2), a.get(.b));
- testing.expectEqual(@as(?usize, 9), a.get(.c));
- testing.expectEqual(@as(?usize, 4), a.get(.d));
-
- a.remove(.a);
- testing.expectEqual(@as(?usize, null), a.fetchRemove(.a));
- testing.expectEqual(@as(?usize, 9), a.fetchRemove(.c));
- a.remove(.c);
-
- var iter = a.iterator();
- const Entry = Map.Entry;
- testing.expectEqual(@as(?Entry, Entry{
- .key = .b,
- .value = &a.values[1],
- }), iter.next());
- testing.expectEqual(@as(?Entry, Entry{
- .key = .d,
- .value = &a.values[3],
- }), iter.next());
- testing.expectEqual(@as(?Entry, null), iter.next());
-}