Add Path.buildParts helper function

main
copygirl 1 year ago
parent c397e3e7d2
commit 51f82576af
  1. 62
      src/path.zig

@ -54,6 +54,31 @@ pub const Path = struct {
pub var default = flecs_c;
};
/// Creates an array of `EntityPath`s with known size equal to the number of
/// elements in the specified tuple argument. Each element of the tuple is
/// either converted to a `.name` part, or an `.id` part.
///
/// Keep in mind the mutability and lifetime of the string elements passed
/// to this function, as they aren't cloned and ownership stays the same.
/// In many cases, the lifetime of `Path`s is relatively short. When this
/// is not the case, it's recommended to `.clone()` the path after creation.
pub fn buildParts(parts: anytype) t: {
if (!std.meta.trait.isTuple(@TypeOf(parts)))
@compileError("Expected tuple, got '" ++ @typeName(@TypeOf(parts)) ++ "'");
const len = @typeInfo(@TypeOf(parts)).Struct.fields.len;
break :t [len]EntityPart;
} {
const len = @typeInfo(@TypeOf(parts)).Struct.fields.len;
var result: [len]EntityPart = undefined;
inline for (&result, parts) |*res, part|
res.* = switch (@TypeOf(part)) {
[]u8, []const u8 => |name| .{ .name = name },
u32, comptime_int => |id| .{ .id = id },
else => @compileError("Expected []u8, []const u8, u32 or comptime_int, got '" ++ @typeName(@TypeOf(part)) ++ "'"),
};
return result;
}
/// Creates a new `Path` from the specified string parts.
///
/// The resulting path does not own any of the given slices.
@ -287,8 +312,22 @@ test Path {
// Alternatively they can be made by specifying the individual component
// parts they're made of, as well as an argument specifying whether it's
// an absolute path.
const absolute1 = try Path.fromParts(true, &.{ .{ .name = "I'm" }, .{ .name = "absolute!" } });
// No need for `deinit()`, does not own outer array nor inner string parts.
// To do this you can use the `buildParts` helper function, which is less
// wordy than building `EntityPart` structs manually.
const absolute1_parts = Path.buildParts(.{ "I'm", "absolute!" });
const absolute1 = try Path.fromParts(true, &absolute1_parts);
// No need to call `deinit()`. The path does not own the `absolute1_parts`
// array nor the string parts, which in this case are comptime constants.
// When handling paths, always be aware of the lifetime of its array and
// any string parts contained within it. This API allows you to completely
// avoid allocation if you know what you are doing.
// In the above example, `absolute_parts` is an array allocated onto the
// stack, and as such will only be valid until the end of the scope. This
// means no allocation is necessary, but it also means `absolute1` is only
// valid for as long as its parts.
// If a path instance is not immediately consumed and you're uncertain
// about the lifetime of its parts, consider using `.clone(alloc)`.
// With `options` unspecified, it's not possible to represent an absolute
// path using a string. Pass your own `FormatOptions` to be able to.
@ -309,12 +348,19 @@ test Path {
try expectEqualStrings("path", relative.parts[2].name);
// Parts can also be numeric ids, used for entities that don't have a name.
const numeric = try Path.fromString("100.101.bar", null, alloc);
defer numeric.deinit();
try expectEqual(@as(usize, 3), numeric.parts.len);
try expectEqual(@as(u32, 100), numeric.parts[0].id);
try expectEqual(@as(u32, 101), numeric.parts[1].id);
try expectEqualStrings("bar", numeric.parts[2].name);
const numeric1 = try Path.fromString("100.101.bar", null, alloc);
defer numeric1.deinit();
try expectEqual(@as(usize, 3), numeric1.parts.len);
try expectEqual(@as(u32, 100), numeric1.parts[0].id);
try expectEqual(@as(u32, 101), numeric1.parts[1].id);
try expectEqualStrings("bar", numeric1.parts[2].name);
// Numeric ids can also be passed to `buildParts`.
const numeric2_parts = Path.buildParts(.{ 100, 101, "bar" });
const numeric2 = try Path.fromParts(false, &numeric2_parts);
// TODO: Let's check numeric1 and numeric2 for equality here.
_ = numeric2;
// Paths are formattable. As format specifier you can use options defined
// on the `FormatOptions` type, or an empty string to use the default.

Loading…
Cancel
Save