pub const UserProvided = union(enum) {
flag: void,
scalar: []const u8,
list: std.ArrayList([]const u8),
map: std.array_hash_map.String(*const UserProvided),
lazy_path: LazyPath,
lazy_path_list: std.ArrayList(LazyPath),
fn eql(a: UserProvided, b: UserProvided) bool {
if (std.meta.activeTag(a) != b) return false;
return switch (a) {
.flag => true,
.scalar => |a_scalar| return mem.eql(u8, a_scalar, b.scalar),
.list => |a_list| {
if (a_list.items.len != b.list.items.len) return false;
for (a_list.items, b.list.items) |a_elem, b_elem| {
if (!mem.eql(u8, a_elem, b_elem))
return false;
}
return true;
},
.map => |a_map| {
if (a_map.count() != b.map.count()) return false;
for (a_map.keys(), a_map.values(), b.map.keys(), b.map.values()) |a_key, a_val, b_key, b_val| {
if (!mem.eql(u8, a_key, b_key)) return false;
if (!a_val.eql(b_val.*)) return false;
}
return true;
},
.lazy_path => |a_lazy_path| return a_lazy_path.eql(b.lazy_path),
.lazy_path_list => |a_lazy_path_list| {
if (a_lazy_path_list.items.len != b.lazy_path_list.items.len) return false;
for (a_lazy_path_list.items, b.lazy_path_list.items) |a_lp, b_lp| {
if (!a_lp.eql(b_lp)) return false;
}
return true;
},
};
}
fn hash(a: UserProvided, hasher: *std.hash.Wyhash) void {
hasher.update(&mem.toBytes(std.meta.activeTag(a)));
switch (a) {
.flag => {},
.scalar => |scalar| hasher.update(scalar),
.list => |*list| for (list.items) |elem| hasher.update(elem),
.map => |*map| for (map.keys(), map.values()) |key, val| {
hasher.update(key);
val.hash(hasher);
},
.lazy_path => |lp| lp.hash(hasher),
.lazy_path_list => |*list| for (list.items) |lp| lp.hash(hasher),
}
}
}