Created
October 26, 2022 02:06
-
-
Save zigster64/6427884e9038a6cfdfbb56a2b6518285 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const Stuff = enum { zeroth, first, second, third, somethingElse }; | |
const OtherStuff = enum { zeroth, first, second, third, somethingElse }; | |
const EnumLookupError = error{InvalidName}; | |
// convert a string into a enum field | |
pub fn stringToEnum(comptime E: type, name: []const u8) EnumLookupError!E { | |
inline for (std.meta.fields(E)) |e| { | |
if (std.mem.eql(u8, name, e.name)) { | |
return @intToEnum(E, e.value); | |
} | |
} | |
return EnumLookupError.InvalidName; | |
} | |
test "lookup enum by name" { | |
// valid lookup by name | |
var stuff = try stringToEnum(Stuff, "second"); | |
try std.testing.expect(stuff == Stuff.second); | |
// use the same function with a different enum type | |
var other_stuff = try stringToEnum(OtherStuff, "third"); | |
try std.testing.expect(other_stuff == OtherStuff.third); | |
// failed lookup by name | |
try std.testing.expectError(EnumLookupError.InvalidName, stringToEnum(Stuff, "notFound")); | |
try std.testing.expectError(EnumLookupError.InvalidName, stringToEnum(OtherStuff, "notFound")); | |
// this is another way to do it, but only works with comptime known names | |
var using_field_access = @field(Stuff, "second"); | |
try std.testing.expect(using_field_access == Stuff.second); | |
} | |
test "wont compile if not an emum" { | |
const notAnEnum = struct { | |
id: usize = 0, | |
}; | |
_ = notAnEnum{}; | |
// uncomment this to produce a horrific amount of compile errors | |
// var this_should_not_compile = try stringToEnum(notAnEnum, "id"); | |
// std.debug.print("got {}\n", .{this_should_not_compile}); | |
} | |
test "convert enum to string" { | |
// just use tagName here, dont need to loop over the fields | |
try std.testing.expect(std.mem.eql(u8, @tagName(Stuff.second), "second")); | |
try std.testing.expect(std.mem.eql(u8, @tagName(OtherStuff.second), "second")); | |
} | |
pub const ArrayOfNames = [][]const u8; | |
// getNamesOfFields returns an array of names of whatever the type is | |
pub fn getNamesOfFields(comptime T: type, allocator: std.mem.Allocator) !ArrayOfNames { | |
const fields = std.meta.fields(T); | |
// create the array first | |
var names: ArrayOfNames = try allocator.alloc([]const u8, fields.len); | |
inline for (fields) |f, index| { | |
names[index] = f.name; | |
} | |
return names; | |
} | |
test "get the names of the enum as an array of strings" { | |
const alloc = std.testing.allocator; | |
var stuffs = try getNamesOfFields(Stuff, std.testing.allocator); | |
defer alloc.free(stuffs); | |
try std.testing.expect(std.mem.eql(u8, stuffs[0], "zeroth")); | |
try std.testing.expect(std.mem.eql(u8, stuffs[1], "first")); | |
try std.testing.expect(std.mem.eql(u8, stuffs[2], "second")); | |
try std.testing.expect(std.mem.eql(u8, stuffs[3], "third")); | |
try std.testing.expect(std.mem.eql(u8, stuffs[4], "somethingElse")); | |
var other_stuffs = try getNamesOfFields(Stuff, std.testing.allocator); | |
defer alloc.free(other_stuffs); | |
try std.testing.expect(std.mem.eql(u8, other_stuffs[0], "zeroth")); | |
try std.testing.expect(std.mem.eql(u8, other_stuffs[1], "first")); | |
try std.testing.expect(std.mem.eql(u8, other_stuffs[2], "second")); | |
try std.testing.expect(std.mem.eql(u8, other_stuffs[3], "third")); | |
try std.testing.expect(std.mem.eql(u8, other_stuffs[4], "somethingElse")); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment