|
|
|
@ -85,3 +85,82 @@ pub fn AnyToType(comptime expr: anytype) type { |
|
|
|
|
else => @compileError("Expression must be a type or a tuple of two types"), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Gets a Flecs-compatible symbol name for the specified type. |
|
|
|
|
/// Supports structs (except anonymous or generic), as well as |
|
|
|
|
/// single-item pointers to supported structs. |
|
|
|
|
/// |
|
|
|
|
/// If the struct defines a public accessible `name`, it is used. |
|
|
|
|
pub fn flecsTypeName(comptime T: type) [:0]const u8 { |
|
|
|
|
const allowed_characters = |
|
|
|
|
"abcdefghijklmnopqrstuvwxyz" ++ |
|
|
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ |
|
|
|
|
"0123456789_"; |
|
|
|
|
switch (@typeInfo(T)) { |
|
|
|
|
.Struct => { |
|
|
|
|
comptime var name: [:0]const u8 = undefined; |
|
|
|
|
comptime if (@hasDecl(T, "name")) { |
|
|
|
|
name = @field(T, "name"); |
|
|
|
|
} else { |
|
|
|
|
name = @typeName(T); |
|
|
|
|
if (std.mem.indexOfScalar(u8, name, '{') != null) |
|
|
|
|
@compileError("Expected type with simple name, got '" ++ @typeName(T) ++ "' (anonymous type?)"); |
|
|
|
|
|
|
|
|
|
// If name includes fully qualified namespace, strip it. |
|
|
|
|
if (std.mem.lastIndexOfScalar(u8, name, '.')) |i| |
|
|
|
|
name = name[(i + 1)..]; |
|
|
|
|
|
|
|
|
|
if (std.mem.indexOfScalar(u8, name, '(') != null) |
|
|
|
|
@compileError("Expected type with simple name, got '" ++ @typeName(T) ++ "' (generic type?)"); |
|
|
|
|
if (std.mem.indexOf(u8, name, "__") != null) |
|
|
|
|
@compileError("Expected type with simple name, got '" ++ @typeName(T) ++ "' (anonymous type?)"); |
|
|
|
|
if (std.mem.indexOfNone(u8, name, allowed_characters) != null) |
|
|
|
|
@compileError("Expected type with simple name, got '" ++ @typeName(T) ++ "' (invalid characters?)"); |
|
|
|
|
}; |
|
|
|
|
return name; |
|
|
|
|
}, |
|
|
|
|
.Pointer => |p| { |
|
|
|
|
if (p.size != .One) |
|
|
|
|
@compileError("Expected struct or single-item pointer, got '" ++ @typeName(T) ++ "'"); |
|
|
|
|
return flecsTypeName(p.child); |
|
|
|
|
}, |
|
|
|
|
else => @compileError("Expected struct or single-item pointer, got '" ++ @typeName(T) ++ "'"), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const expect = @import("./test/expect.zig"); |
|
|
|
|
|
|
|
|
|
test flecsTypeName { |
|
|
|
|
const Foo = struct {}; |
|
|
|
|
try expect.equal("Foo", flecsTypeName(Foo)); |
|
|
|
|
try expect.equal("Foo", flecsTypeName(*Foo)); |
|
|
|
|
|
|
|
|
|
const Bar = struct { |
|
|
|
|
const Baz = struct { |
|
|
|
|
const Quux = struct {}; |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|
try expect.equal("Quux", flecsTypeName(Bar.Baz.Quux)); |
|
|
|
|
|
|
|
|
|
try expect.equal("Anon", flecsTypeName((struct { |
|
|
|
|
const Anon = struct {}; |
|
|
|
|
}).Anon)); |
|
|
|
|
|
|
|
|
|
try expect.equal("Random", flecsTypeName(std.Random)); |
|
|
|
|
|
|
|
|
|
// error: Expected struct or single-item pointer, got 'i32' |
|
|
|
|
// _ = flecsTypeName(i32); |
|
|
|
|
|
|
|
|
|
// error: Expected type with simple name, got 'array_list.ArrayListAligned(i32,null)' (generic type?) |
|
|
|
|
// _ flecsTypeName(std.ArrayList(i32)); |
|
|
|
|
|
|
|
|
|
// error: Expected type with simple name, got 'meta.decltest.flecsTypeName__struct_...' (anonymous type?) |
|
|
|
|
// _ = flecsTypeName(struct {}); |
|
|
|
|
|
|
|
|
|
// error: Expected type with simple name, got 'struct{comptime foo: comptime_int = 0}' (anonymous type?) |
|
|
|
|
// _ = flecsTypeName(@TypeOf(.{ .foo = 0 })); |
|
|
|
|
|
|
|
|
|
// error: Expected type with simple name, got 'meta.decltest.flecsTypeName.%&!*' (invalid characters?) |
|
|
|
|
// const @"%&!*" = struct {}; |
|
|
|
|
// _ = flecsTypeName(@"%&!*"); |
|
|
|
|
} |
|
|
|
|