feature. See also
. The project being documented here (as the example) is the Zig library itself.
Build.OrderedUserValue
const OrderedUserValue = union(enum)
File
Code
const OrderedUserValue = union(enum) {
flag: void,
scalar: []const u8,
list: std.array_list.Managed([]const u8),
map: std.array_list.Managed(Pair),
lazy_path: LazyPath,
lazy_path_list: std.array_list.Managed(LazyPath),
const Pair = struct {
name: []const u8,
value: OrderedUserValue,
fn lessThan(_: void, lhs: Pair, rhs: Pair) bool {
return std.ascii.lessThanIgnoreCase(lhs.name, rhs.name);
}
};
fn hash(val: OrderedUserValue, hasher: *std.hash.Wyhash) void {
hasher.update(&std.mem.toBytes(std.meta.activeTag(val)));
switch (val) {
.flag => {},
.scalar => |scalar| hasher.update(scalar),
.list => |list| for (list.items) |list_entry|
hasher.update(list_entry),
.map => |map| for (map.items) |map_entry| {
hasher.update(map_entry.name);
map_entry.value.hash(hasher);
},
.lazy_path => |lp| hashLazyPath(lp, hasher),
.lazy_path_list => |lp_list| for (lp_list.items) |lp| {
hashLazyPath(lp, hasher);
},
}
}
fn hashLazyPath(lp: LazyPath, hasher: *std.hash.Wyhash) void {
switch (lp) {
.src_path => |sp| {
hasher.update(sp.owner.pkg_hash);
hasher.update(sp.sub_path);
},
.generated => |gen| {
hasher.update(@ptrCast(&gen.index));
hasher.update(@ptrCast(&gen.up));
hasher.update(gen.sub_path);
},
.cwd_relative => |rel_path| {
hasher.update(rel_path);
},
.relative => |r| {
hasher.update(@ptrCast(&r.base));
hasher.update(@ptrCast(&r.sub_path));
},
.dependency => |dep| {
hasher.update(dep.dependency.builder.pkg_hash);
hasher.update(dep.sub_path);
},
}
}
fn mapFromUnordered(allocator: Allocator, unordered: std.StringHashMap(*const UserValue)) std.array_list.Managed(Pair) {
var ordered = std.array_list.Managed(Pair).init(allocator);
var it = unordered.iterator();
while (it.next()) |entry| {
ordered.append(.{
.name = entry.key_ptr.*,
.value = OrderedUserValue.fromUnordered(allocator, entry.value_ptr.*.*),
}) catch @panic("OOM");
}
std.mem.sortUnstable(Pair, ordered.items, {}, Pair.lessThan);
return ordered;
}
fn fromUnordered(allocator: Allocator, unordered: UserValue) OrderedUserValue {
return switch (unordered) {
.flag => .{ .flag = {} },
.scalar => |scalar| .{ .scalar = scalar },
.list => |list| .{ .list = list },
.map => |map| .{ .map = OrderedUserValue.mapFromUnordered(allocator, map) },
.lazy_path => |lp| .{ .lazy_path = lp },
.lazy_path_list => |list| .{ .lazy_path_list = list },
};
}
}