Fix Path.buildParts

main
copygirl 1 year ago
parent 51f82576af
commit edadf3e1df
  1. 42
      src/path.zig

@ -70,12 +70,21 @@ pub const Path = struct {
} { } {
const len = @typeInfo(@TypeOf(parts)).Struct.fields.len; const len = @typeInfo(@TypeOf(parts)).Struct.fields.len;
var result: [len]EntityPart = undefined; var result: [len]EntityPart = undefined;
inline for (&result, parts) |*res, part| inline for (&result, parts) |*res, part| {
res.* = switch (@TypeOf(part)) { const msg = "Expected '[]const u8' or 'u32', got '" ++ @typeName(@TypeOf(part)) ++ "'";
[]u8, []const u8 => |name| .{ .name = name }, res.* = switch (@typeInfo(@TypeOf(part))) {
u32, comptime_int => |id| .{ .id = id }, .Pointer => |p| switch (p.size) {
else => @compileError("Expected []u8, []const u8, u32 or comptime_int, got '" ++ @typeName(@TypeOf(part)) ++ "'"), .One => switch (@typeInfo(p.child)) {
.Array => |a| if (a.child == u8) .{ .name = part } else @compileError(msg),
else => @compileError(msg),
},
.Slice => if (p.child == u8) .{ .name = part } else @compileError(msg),
else => @compileError(msg),
},
.Int, .ComptimeInt => .{ .id = part },
else => @compileError(msg),
}; };
}
return result; return result;
} }
@ -130,12 +139,24 @@ pub const Path = struct {
}; };
} }
/// Creates a `Path` for the specified `child` entity, optionally in
/// relation to the specified `parent` entity. If `parent` is not `null`,
/// the resulting path is relative. Otherwise it will be absolute.
///
/// This function allocates an array for the parts that make up the entity's
/// path, however each part itself is owned by Flecs and could change or be
/// invalidated ay any time, such as when an entity is renamed or removed.
pub fn fromEntity(comptime ctx: type, parent: ?Entity(ctx), child: Entity(ctx), alloc: Allocator) !Path { pub fn fromEntity(comptime ctx: type, parent: ?Entity(ctx), child: Entity(ctx), alloc: Allocator) !Path {
if (parent) |p| std.debug.assert(p.raw != 0);
std.debug.assert(child.raw != 0); std.debug.assert(child.raw != 0);
if (parent) |p| {
std.debug.assert(p.raw != 0);
std.debug.assert(p.raw != child.raw);
}
// TODO: Use a threadlocal field with reasonable size, then clone the result.
const starting_capacity: usize = 12; const starting_capacity: usize = 12;
var parts = try alloc.alloc(EntityPart, starting_capacity); var parts = try alloc.alloc(EntityPart, starting_capacity);
errdefer alloc.free(parts);
var num_parts: usize = 0; var num_parts: usize = 0;
// Traverse up the entity hierarchy starting from the specified child // Traverse up the entity hierarchy starting from the specified child
@ -148,7 +169,14 @@ pub const Path = struct {
else else
.{ .id = current.getEntityId() }; .{ .id = current.getEntityId() };
num_parts += 1; num_parts += 1;
current = current.getParent() orelse break;
// Move to the parent entity, if any.
current = current.getParent() orelse
// If `parent` wasn't specified, we reached the root. Done.
// Otherwise, if the parent wasn't found, return an error.
if (parent == null) break else return error.ParentNotFound;
// If we reached the specified `parent`, we're done here!
if (parent != null and current.raw == parent.?.raw) break; if (parent != null and current.raw == parent.?.raw) break;
} }

Loading…
Cancel
Save