Based on this post:
Solved by just parsing manualy.
const BuildZigZon = struct {
name: ?[]const u8 = null,
version: ?[]const u8 = null,
dependencies: std.StringArrayHashMapUnmanaged(Dependency) = .empty,
const Dependency = struct {
url: []const u8 = "",
hash: []const u8 = "",
path: []const u8 = "",
lazy: bool = false,
};
};
fn openBuildZigZon(arena: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) !BuildZigZon {
const content = try dir.readFileAllocOpt…
I changed the fields of Dependency to optionals so that later code still has the info whether the field was present:
var zondata: [:0]const u8 =
\\.{
\\ .name = .foo,
\\ .version = "0.0.0",
\\ .fingerprint = 0x1879e3171df18555,
\\ .minimum_zig_version = "0.15.1",
\\ .dependencies = .{
\\ .capy = .{
\\ .url = "git+https://github.com/capy-ui/capy#bb12dab974a310b737acbaa6649cc2f2f8f8455f",
\\ .hash = "capy-0.4.1-kru7R1I2ZQS55Kk-HN_p8YDKCdkgGhmJe8f0Gq0djDfd",
\\ },
\\ },
\\ .paths = .{
\\ "build.zig",
\\ "build.zig.zon",
\\ "src",
\\ },
\\}
;
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var arena: std.heap.ArenaAllocator = .init(allocator);
defer arena.deinit();
const parsed = try parseBuildZigZon(arena.allocator(), zondata);
std.debug.print("{?s}\n", .{parsed.name});
var it = parsed.dependencies.iterator();
while (it.next()) |dependency| {
std.debug.print("{s}\n", .{dependency.key_ptr.*});
std.debug.print("{?s}\n", .{dependency.value_ptr.url});
std.debug.print("{?s}\n", .{dependency.value_ptr.hash});
std.debug.print("{?s}\n", .{dependency.value_ptr.path});
std.debug.print("{?}\n", .{dependency.value_ptr.lazy});
}
}
const BuildZigZon = struct {
name: ?[]const u8 = null,
version: ?[]const u8 = null,
dependencies: std.StringArrayHashMapUnmanaged(Dependency) = .empty,
const Dependency = struct {
url: ?[]const u8 = null,
hash: ?[]const u8 = null,
path: ?[]const u8 = null,
lazy: ?bool = null,
};
};
fn parseBuildZigZon(arena: std.mem.Allocator, content: [:0]const u8) !BuildZigZon {
const ast = try std.zig.Ast.parse(arena, content, .zon);
const zoir = try std.zig.ZonGen.generate(arena, ast, .{ .parse_str_lits = true });
const root = std.zig.Zoir.Node.Index.root.get(zoir);
const root_struct = if (root == .struct_literal) root.struct_literal else return error.Parse;
var result: BuildZigZon = .{};
for (root_struct.names, 0..root_struct.vals.len) |name_node, index| {
const value = root_struct.vals.at(@intCast(index));
const name = name_node.get(zoir);
if (std.mem.eql(u8, name, "name")) {
result.name = try arena.dupe(u8, value.get(zoir).enum_literal.get(zoir));
}
if (std.mem.eql(u8, name, "version")) {
result.version = try arena.dupe(u8, value.get(zoir).string_literal);
}
if (std.mem.eql(u8, name, "dependencies")) dep: {
switch (value.get(zoir)) {
.struct_literal => |sl| {
for (sl.names, 0..sl.vals.len) |dep_name, dep_index| {
const node = sl.vals.at(@intCast(dep_index));
const dep_body = try std.zon.parse.fromZoirNode(BuildZigZon.Dependency, arena, ast, zoir, node, null, .{});
try result.dependencies.put(arena, try arena.dupe(u8, dep_name.get(zoir)), dep_body);
}
},
.empty_literal => {
break :dep;
},
else => return error.Parse,
}
}
}
return result;
}
const std = @import("std");
I didn’t see a compelling reason (was too lazy) to change the StringArrayHashMap to a slice, so that is left as an exercise for the reader.