mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-02 07:58:37 +00:00
lib: enum func
This commit is contained in:
85
src/lib/enum.zig
Normal file
85
src/lib/enum.zig
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// Create an enum type with the given keys that is C ABI compatible
|
||||||
|
/// if we're targeting C, otherwise a Zig enum with smallest possible
|
||||||
|
/// backing type.
|
||||||
|
///
|
||||||
|
/// In all cases, the enum keys will be created in the order given.
|
||||||
|
/// For C ABI, this means that the order MUST NOT be changed in order
|
||||||
|
/// to preserve ABI compatibility. You can set a key to null to
|
||||||
|
/// remove it from the Zig enum while keeping the "hole" in the C enum
|
||||||
|
/// to preserve ABI compatibility.
|
||||||
|
///
|
||||||
|
/// C detection is up to the caller, since there are multiple ways
|
||||||
|
/// to do that. We rely on the `target` parameter to determine whether we
|
||||||
|
/// should create a C compatible enum or a Zig enum.
|
||||||
|
///
|
||||||
|
/// For the Zig enum, the enum value is not guaranteed to be stable, so
|
||||||
|
/// it shouldn't be relied for things like serialization.
|
||||||
|
pub fn Enum(
|
||||||
|
target: Target,
|
||||||
|
keys: []const ?[:0]const u8,
|
||||||
|
) type {
|
||||||
|
var fields: [keys.len]std.builtin.Type.EnumField = undefined;
|
||||||
|
var fields_i: usize = 0;
|
||||||
|
for (keys, 0..) |key_, key_i| {
|
||||||
|
const key: [:0]const u8 = key_ orelse switch (target) {
|
||||||
|
.c => std.fmt.comptimePrint("__unused_{d}", .{key_i}),
|
||||||
|
.zig => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
fields[fields_i] = .{
|
||||||
|
.name = key,
|
||||||
|
.value = fields_i,
|
||||||
|
};
|
||||||
|
fields_i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return @Type(.{ .@"enum" = .{
|
||||||
|
.tag_type = switch (target) {
|
||||||
|
.c => c_int,
|
||||||
|
.zig => std.math.IntFittingRange(0, fields_i - 1),
|
||||||
|
},
|
||||||
|
.fields = fields[0..fields_i],
|
||||||
|
.decls = &.{},
|
||||||
|
.is_exhaustive = true,
|
||||||
|
} });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Target = union(enum) {
|
||||||
|
c,
|
||||||
|
zig,
|
||||||
|
};
|
||||||
|
|
||||||
|
test "zig" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const T = Enum(.zig, &.{ "a", "b", "c", "d" });
|
||||||
|
const info = @typeInfo(T).@"enum";
|
||||||
|
try testing.expectEqual(u2, info.tag_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "c" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const T = Enum(.c, &.{ "a", "b", "c", "d" });
|
||||||
|
const info = @typeInfo(T).@"enum";
|
||||||
|
try testing.expectEqual(c_int, info.tag_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "abi by removing a key" {
|
||||||
|
const testing = std.testing;
|
||||||
|
// C
|
||||||
|
{
|
||||||
|
const T = Enum(.c, &.{ "a", "b", null, "d" });
|
||||||
|
const info = @typeInfo(T).@"enum";
|
||||||
|
try testing.expectEqual(c_int, info.tag_type);
|
||||||
|
try testing.expectEqual(3, @intFromEnum(T.d));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zig
|
||||||
|
{
|
||||||
|
const T = Enum(.zig, &.{ "a", "b", null, "d" });
|
||||||
|
const info = @typeInfo(T).@"enum";
|
||||||
|
try testing.expectEqual(u2, info.tag_type);
|
||||||
|
try testing.expectEqual(2, @intFromEnum(T.d));
|
||||||
|
}
|
||||||
|
}
|
10
src/lib/main.zig
Normal file
10
src/lib/main.zig
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const enumpkg = @import("enum.zig");
|
||||||
|
|
||||||
|
pub const allocator = @import("allocator.zig");
|
||||||
|
pub const Enum = enumpkg.Enum;
|
||||||
|
pub const EnumTarget = enumpkg.Target;
|
||||||
|
|
||||||
|
test {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
@@ -80,6 +80,7 @@ comptime {
|
|||||||
test {
|
test {
|
||||||
_ = terminal;
|
_ = terminal;
|
||||||
|
|
||||||
// Tests always test the C API
|
// Tests always test the C API and shared C functions
|
||||||
_ = terminal.c_api;
|
_ = terminal.c_api;
|
||||||
|
_ = @import("lib/main.zig");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user