| ... | ... | @@ -240,7 +240,7 @@ test nameCast { |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | /// A set of enum elements, backed by a bitfield. If the enum |
| 243 | | /// is not dense, a mapping will be constructed from enum values |
| 243 | /// is exhaustive but not dense, a mapping will be constructed from enum values |
| 244 | 244 | /// to dense indices. This type does no dynamic allocation and |
| 245 | 245 | /// can be copied by value. |
| 246 | 246 | pub fn EnumSet(comptime E: type) type { |
| ... | ... | @@ -263,11 +263,21 @@ pub fn EnumSet(comptime E: type) type { |
| 263 | 263 | pub fn init(init_values: EnumFieldStruct(E, bool, false)) Self { |
| 264 | 264 | @setEvalBranchQuota(2 * @typeInfo(E).Enum.fields.len); |
| 265 | 265 | var result: Self = .{}; |
| 266 | | inline for (0..Self.len) |i| { |
| 267 | | const key = comptime Indexer.keyForIndex(i); |
| 268 | | const tag = @tagName(key); |
| 269 | | if (@field(init_values, tag)) { |
| 270 | | result.bits.set(i); |
| 266 | if (@typeInfo(E).Enum.is_exhaustive) { |
| 267 | inline for (0..Self.len) |i| { |
| 268 | const key = comptime Indexer.keyForIndex(i); |
| 269 | const tag = @tagName(key); |
| 270 | if (@field(init_values, tag)) { |
| 271 | result.bits.set(i); |
| 272 | } |
| 273 | } |
| 274 | } else { |
| 275 | inline for (std.meta.fields(E)) |field| { |
| 276 | const key = @field(E, field.name); |
| 277 | if (@field(init_values, field.name)) { |
| 278 | const i = comptime Indexer.indexOf(key); |
| 279 | result.bits.set(i); |
| 280 | } |
| 271 | 281 | } |
| 272 | 282 | } |
| 273 | 283 | return result; |
| ... | ... | @@ -416,7 +426,7 @@ pub fn EnumSet(comptime E: type) type { |
| 416 | 426 | } |
| 417 | 427 | |
| 418 | 428 | /// A map keyed by an enum, backed by a bitfield and a dense array. |
| 419 | | /// If the enum is not dense, a mapping will be constructed from |
| 429 | /// If the enum is exhaustive but not dense, a mapping will be constructed from |
| 420 | 430 | /// enum values to dense indices. This type does no dynamic |
| 421 | 431 | /// allocation and can be copied by value. |
| 422 | 432 | pub fn EnumMap(comptime E: type, comptime V: type) type { |
| ... | ... | @@ -444,12 +454,23 @@ pub fn EnumMap(comptime E: type, comptime V: type) type { |
| 444 | 454 | pub fn init(init_values: EnumFieldStruct(E, ?Value, null)) Self { |
| 445 | 455 | @setEvalBranchQuota(2 * @typeInfo(E).Enum.fields.len); |
| 446 | 456 | var result: Self = .{}; |
| 447 | | inline for (0..Self.len) |i| { |
| 448 | | const key = comptime Indexer.keyForIndex(i); |
| 449 | | const tag = @tagName(key); |
| 450 | | if (@field(init_values, tag)) |*v| { |
| 451 | | result.bits.set(i); |
| 452 | | result.values[i] = v.*; |
| 457 | if (@typeInfo(E).Enum.is_exhaustive) { |
| 458 | inline for (0..Self.len) |i| { |
| 459 | const key = comptime Indexer.keyForIndex(i); |
| 460 | const tag = @tagName(key); |
| 461 | if (@field(init_values, tag)) |*v| { |
| 462 | result.bits.set(i); |
| 463 | result.values[i] = v.*; |
| 464 | } |
| 465 | } |
| 466 | } else { |
| 467 | inline for (std.meta.fields(E)) |field| { |
| 468 | const key = @field(E, field.name); |
| 469 | if (@field(init_values, field.name)) |*v| { |
| 470 | const i = comptime Indexer.indexOf(key); |
| 471 | result.bits.set(i); |
| 472 | result.values[i] = v.*; |
| 473 | } |
| 453 | 474 | } |
| 454 | 475 | } |
| 455 | 476 | return result; |
| ... | ... | @@ -1222,6 +1243,23 @@ test "EnumSet const iterator" { |
| 1222 | 1243 | try testing.expect(result.eql(diag_move)); |
| 1223 | 1244 | } |
| 1224 | 1245 | |
| 1246 | test "EnumSet non-exhaustive" { |
| 1247 | const BitIndices = enum(u4) { |
| 1248 | a = 0, |
| 1249 | b = 1, |
| 1250 | c = 4, |
| 1251 | _, |
| 1252 | }; |
| 1253 | const BitField = EnumSet(BitIndices); |
| 1254 | |
| 1255 | var flags = BitField.init(.{ .a = true, .b = true }); |
| 1256 | flags.insert(.c); |
| 1257 | flags.remove(.a); |
| 1258 | try testing.expect(!flags.contains(.a)); |
| 1259 | try testing.expect(flags.contains(.b)); |
| 1260 | try testing.expect(flags.contains(.c)); |
| 1261 | } |
| 1262 | |
| 1225 | 1263 | pub fn EnumIndexer(comptime E: type) type { |
| 1226 | 1264 | // Assumes that the enum fields are sorted in ascending order (optimistic). |
| 1227 | 1265 | // Unsorted enums may require the user to manually increase the quota. |