diff --git a/.gitignore b/.gitignore index 341ea5dbb61d8c9d0f60457b0b9641cbb35dfbeb..73c26b5e7e9cfcbad96967572789ee222efaf47b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -zig-cache .zig-cache zig-out deps.zig .zigmod +files.zig zigmod.lock diff --git a/build.zig b/build.zig index 11d18262368447f65df3e81927ab709237fb8cba..5f1250f230163c565f5e7e340cc8fdd1c152439f 100644 --- a/build.zig +++ b/build.zig @@ -1,23 +1,20 @@ const std = @import("std"); const deps = @import("./deps.zig"); -pub fn build(b: *std.build.Builder) void { - // Standard target options allows the person running `zig build` to choose - // what target to build for. Here we do not override the defaults, which - // means any target is allowed, and the default is native. Other options - // for restricting supported target set are available. +pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); + const mode = b.option(std.builtin.Mode, "mode", "") orelse .Debug; - // Standard release options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. - const mode = b.standardReleaseOptions(); + const exe = b.addExecutable(.{ + .name = "zig-licenses", + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = mode, + }); + deps.addAllTo(exe); + b.installArtifact(exe); - const exe = b.addExecutable("zig-licenses", "src/main.zig"); - exe.setTarget(target); - exe.setBuildMode(mode); - exe.install(); - - const run_cmd = exe.run(); + const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd.addArgs(args); @@ -28,13 +25,16 @@ pub fn build(b: *std.build.Builder) void { // - const exe2 = b.addExecutable("generate", "generate.zig"); - exe2.setTarget(target); - exe2.setBuildMode(mode); + const exe2 = b.addExecutable(.{ + .name = "generate", + .root_source_file = b.path("generate.zig"), + .target = target, + .optimize = mode, + }); deps.addAllTo(exe2); - exe2.install(); + b.installArtifact(exe2); - const run_cmd2 = exe2.run(); + const run_cmd2 = b.addRunArtifact(exe2); run_cmd2.step.dependOn(b.getInstallStep()); if (b.args) |args| { run_cmd2.addArgs(args); diff --git a/generate.zig b/generate.zig index bc95de3cd1246cb708c4d366c6aa283a42a5d70e..0f693298a351e708ded4e74a933a94d5e8e2539f 100644 --- a/generate.zig +++ b/generate.zig @@ -1,33 +1,34 @@ //! Run this with `zig build gen` const std = @import("std"); -const zfetch = @import("zfetch"); const json = @import("json"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - const alloc = &gpa.allocator; + const alloc = gpa.allocator(); const f = try std.fs.cwd().createFile("src/lib.zig", .{}); const w = f.writer(); { std.log.info("spdx", .{}); - const val = try simple_fetch(alloc, "https://raw.githubusercontent.com/spdx/license-list-data/master/json/licenses.json"); + const doc = try simple_fetch(alloc, "https://raw.githubusercontent.com/spdx/license-list-data/master/json/licenses.json"); + defer doc.deinit(alloc); + const val = doc.root.object(); try w.writeAll("// SPDX License Data generated from https://github.com/spdx/license-list-data\n"); try w.writeAll("//\n"); - try w.print("// Last generated from version {s}\n", .{val.get("licenseListVersion").?.String}); + try w.print("// Last generated from version {s}\n", .{val.getS("licenseListVersion").?}); try w.writeAll("//\n"); - var licenses = val.get("licenses").?.Array; - std.sort.sort(json.Value, licenses, {}, spdxlicenseLessThan); + const licenses = try mutdupe(alloc, json.ValueIndex, val.getA("licenses").?); + std.mem.sort(json.ValueIndex, licenses, {}, spdxlicenseLessThan); try w.writeAll("\n"); try w.writeAll("pub const spdx = &[_][]const u8{\n"); for (licenses) |lic| { try w.print(" \"{s}\",\n", .{ - lic.get("licenseId").?.String, + lic.object().getS("licenseId").?, }); } try w.writeAll("};\n"); @@ -35,28 +36,31 @@ pub fn main() !void { try w.writeAll("\n"); try w.writeAll("pub const osi = &[_][]const u8{\n"); for (licenses) |lic| { - if (!lic.get("isOsiApproved").?.Bool) continue; - try w.print(" \"{s}\",\n", .{lic.get("licenseId").?.String}); + if (!lic.object().getB("isOsiApproved").?) continue; + try w.print(" \"{s}\",\n", .{lic.object().getS("licenseId").?}); } try w.writeAll("};\n"); } { std.log.info("blueoak", .{}); - const val = try simple_fetch(alloc, "https://blueoakcouncil.org/list.json"); + const doc = try simple_fetch(alloc, "https://blueoakcouncil.org/list.json"); + defer doc.deinit(alloc); + const val = doc.root.object(); + try w.writeAll("\n"); try w.writeAll("// Blue Oak Council data generated from https://blueoakcouncil.org/list\n"); try w.writeAll("//\n"); - try w.print("// Last generated from version {s}\n", .{val.get("version").?.String}); + try w.print("// Last generated from version {s}\n", .{val.getS("version").?}); try w.writeAll("//\n"); try w.writeAll("\n"); try w.writeAll("pub const blueoak = struct {\n"); - for (val.get("ratings").?.Array) |rating| { - try w.print(" pub const {s} = &[_][]const u8{{\n", .{std.ascii.allocLowerString(alloc, rating.get("name").?.String)}); - for (rating.get("licenses").?.Array) |lic| { + for (val.getA("ratings").?) |rating| { + try w.print(" pub const {s} = &[_][]const u8{{\n", .{try std.ascii.allocLowerString(alloc, rating.object().getS("name").?)}); + for (rating.object().getA("licenses").?) |lic| { try w.print(" \"{s}\",\n", .{ - lic.get("id").?.String, + lic.object().getS("id").?, }); } try w.print(" }};\n", .{}); @@ -65,19 +69,31 @@ pub fn main() !void { } } -pub fn simple_fetch(alloc: *std.mem.Allocator, url: []const u8) !json.Value { - const req = try zfetch.Request.init(alloc, url, null); - defer req.deinit(); - try req.do(.GET, null, null); - const r = req.reader(); - const body_content = try r.readAllAlloc(alloc, std.math.maxInt(usize)); - const val = try json.parse(alloc, body_content); - return val; +pub fn simple_fetch(alloc: std.mem.Allocator, url: []const u8) !json.Document { + var client = std.http.Client{ .allocator = alloc }; + defer client.deinit(); + + var list = std.ArrayList(u8).init(alloc); + defer list.deinit(); + + const fetch = try client.fetch(.{ + .location = .{ .url = url }, + .response_storage = .{ .dynamic = &list }, + }); + const opts = json.Parser.Options{ .maximum_depth = 100, .support_trailing_commas = true }; + if (fetch.status != .ok) return try json.parseFromSlice(alloc, url, "{}", opts); + return try json.parseFromSlice(alloc, url, list.items, opts); } -fn spdxlicenseLessThan(context: void, lhs: json.Value, rhs: json.Value) bool { +fn spdxlicenseLessThan(context: void, lhs: json.ValueIndex, rhs: json.ValueIndex) bool { _ = context; - const l = lhs.get("licenseId").?.String; - const r = rhs.get("licenseId").?.String; + const l = lhs.object().getS("licenseId").?; + const r = rhs.object().getS("licenseId").?; return std.mem.lessThan(u8, l, r); } + +fn mutdupe(alloc: std.mem.Allocator, comptime T: type, original: anytype) ![]T { + const slice = try alloc.alloc(T, original.len); + for (original, 0..) |item, i| slice[i] = item; + return slice; +} diff --git a/licenses.txt b/licenses.txt new file mode 100644 index 0000000000000000000000000000000000000000..666d1639705b3783bad59e28a3d460c5bf0d775f --- /dev/null +++ b/licenses.txt @@ -0,0 +1,10 @@ +MIT: += https://spdx.org/licenses/MIT +- This +- git https://github.com/nektro/zig-extras +- git https://github.com/nektro/zig-json +- git https://github.com/nektro/zig-tracer + +MPL-2.0: += https://spdx.org/licenses/MPL-2.0 +- git https://github.com/nektro/zig-intrusive-parser diff --git a/zig.mod b/zig.mod index 7e22ffea99b05198a680a701f0505fa44c995d5f..ed103de8ecea48b397164d33730bdb4fb43c1df4 100644 --- a/zig.mod +++ b/zig.mod @@ -4,5 +4,4 @@ main: src/lib.zig license: MIT dev_dependencies: - - src: git https://github.com/truemedian/zfetch - src: git https://github.com/nektro/zig-json