about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/exe.zig19
-rw-r--r--src/fs.zig9
-rw-r--r--src/gen.zig80
3 files changed, 66 insertions, 42 deletions
diff --git a/src/exe.zig b/src/exe.zig
index 8624193..4d55c72 100644
--- a/src/exe.zig
+++ b/src/exe.zig
@@ -82,8 +82,11 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void {
     const f = try fs.FileSwapper.createAt(ctx.allocator(), target_path);
     defer f.close();
 
+    var buffer: [1024]u8 = undefined;
+    var w = f.writer(&buffer);
+
     // open new scope to close the file swapper when we're done writing
-    try f.writer().print(
+    try w.interface.print(
         \\<!-- Generated file, you may edit and discard {s} :) -->
         \\
     ,
@@ -107,7 +110,7 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void {
         "--strip-comments",
         "--output=-",
         source_path,
-    }, &env_map, f.writer().any());
+    }, &env_map, &w.interface);
 
     // swap now, we want to edit mtime
     try f.swap();
@@ -118,7 +121,7 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void {
     try fs.setMtime(target_path, mtime);
 }
 
-pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.process.EnvMap, buf: std.io.AnyWriter) !void {
+pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.process.EnvMap, w: *std.Io.Writer) !void {
     const command = try std.mem.join(ctx.allocator(), " ", argv);
     defer ctx.allocator().free(command);
     const label = try std.fmt.allocPrint(ctx.allocator(), "running {s}", .{command});
@@ -127,14 +130,22 @@ pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.pro
     ctx.progress_start(label);
     defer ctx.progress_end();
 
+    log.debug("running {s}", .{command});
+
     var p = std.process.Child.init(argv, std.heap.page_allocator);
+    p.stdin_behavior = .Ignore;
     p.stdout_behavior = .Pipe;
+    p.stderr_behavior = .Ignore;
     p.progress_node = ctx.progress_nodes.getLast();
     p.env_map = env_map;
 
     try p.spawn();
 
-    try buf.writeFile(p.stdout.?);
+    var buffer: [1024]u8 = undefined;
+    var r = p.stdout.?.readerStreaming(&buffer);
+
+    _ = try w.sendFileAll(&r, .unlimited);
+    try w.flush();
 
     const result = try p.wait();
     _ = result;
diff --git a/src/fs.zig b/src/fs.zig
index d6c182d..4e42f44 100644
--- a/src/fs.zig
+++ b/src/fs.zig
@@ -43,8 +43,8 @@ pub const FileSwapper = struct {
         return self.tmp;
     }
 
-    pub fn writer(self: FileSwapper) std.fs.File.Writer {
-        return self.tmp.writer();
+    pub fn writer(self: FileSwapper, buffer: []u8) std.fs.File.Writer {
+        return self.tmp.writer(buffer);
     }
 
     pub fn diff(self: FileSwapper) !bool {
@@ -133,7 +133,6 @@ pub fn joinPathAndFilename(alloc: std.mem.Allocator, paths: []const []const u8,
     const filename = try std.mem.concat(fba.allocator(), u8, filename_parts);
 
     var p = try std.ArrayList([]const u8).initCapacity(fba.allocator(), paths.len + 1);
-    defer p.deinit();
 
     p.appendSliceAssumeCapacity(paths);
     p.appendAssumeCapacity(filename);
@@ -171,8 +170,8 @@ pub fn getMtime(path: []const u8) !std.posix.timespec {
     const fd = try std.fs.cwd().openFile(path, .{ .mode = .read_only });
     defer fd.close();
 
-    const meta = try fd.metadata();
-    const mtime = meta.modified();
+    const meta = try fd.stat();
+    const mtime = meta.mtime;
 
     return .{
         .sec = std.math.cast(isize, @divFloor(mtime, std.time.ns_per_s)) orelse std.math.maxInt(isize),
diff --git a/src/gen.zig b/src/gen.zig
index 3245e7c..eb768e5 100644
--- a/src/gen.zig
+++ b/src/gen.zig
@@ -65,7 +65,10 @@ fn genIndex(ctx: *Context) !void {
     const f = try fs.FileSwapper.createAt(ctx.allocator(), srcpathIndex);
     defer f.close();
 
-    try f.writer().writeAll(
+    var buffer: [1024]u8 = undefined;
+    var w = f.writer(&buffer);
+
+    try w.interface.writeAll(
         \\<ul class="col2 captial">
         \\
     );
@@ -89,7 +92,7 @@ fn genIndex(ctx: *Context) !void {
         const dstpath = try fs.joinPathAndFilename(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" });
         defer ctx.allocator().free(dstpath);
 
-        try f.writer().print(
+        try w.interface.print(
             \\<li><a href="/{[LINK]s}">{[NAME]s}</a></li>
             \\
         , .{
@@ -98,11 +101,13 @@ fn genIndex(ctx: *Context) !void {
         });
     }
 
-    try f.writer().writeAll(
+    try w.interface.writeAll(
         \\</ul>
         \\
     );
 
+    try w.interface.flush();
+
     if (!try f.diff()) try f.undo();
 }
 
@@ -138,16 +143,19 @@ fn genSite(ctx: *Context) !void {
         const f = try fs.FileSwapper.createAt(ctx.allocator(), dstpath);
         defer f.close();
 
+        var buffer: [1024]u8 = undefined;
+        var w = f.writer(&buffer);
+
         const page_name = try std.mem.replaceOwned(u8, ctx.allocator(), dstname, "_", " ");
         defer ctx.allocator().free(page_name);
 
-        try build(ctx.allocator(), f.writer().any(), page_name, srcpath);
+        try build(ctx.allocator(), &w.interface, page_name, srcpath);
         ctx.generated += 1;
     }
 }
 
 // build a single html file
-fn build(allocator: std.mem.Allocator, w: std.io.AnyWriter, page_name: []const u8, srcpath: []const u8) !void {
+fn build(allocator: std.mem.Allocator, w: *std.Io.Writer, page_name: []const u8, srcpath: []const u8) !void {
     const mtime = try fs.getMtime(srcpath);
     const mtime_str = try fs.formatTimespec(allocator, mtime, "%F");
     defer allocator.free(mtime_str);
@@ -235,6 +243,8 @@ fn build(allocator: std.mem.Allocator, w: std.io.AnyWriter, page_name: []const u
         \\</html>
         \\
     );
+
+    try w.flush();
 }
 
 // build a virtual html file, currently either:
@@ -266,7 +276,10 @@ fn meta(ctx: *Context, p: []const u8) !void {
         const f = try fs.FileSwapper.createAt(ctx.allocator(), dstpath);
         defer f.close();
 
-        try f.writer().print(
+        var buffer: [1024]u8 = undefined;
+        var w = f.writer(&buffer);
+
+        try w.interface.print(
             \\<!DOCTYPE html>
             \\<html lang="en">
             \\<head>
@@ -287,6 +300,7 @@ fn meta(ctx: *Context, p: []const u8) !void {
         , .{
             .LINK = link,
         });
+        try w.interface.flush();
 
         ctx.tilde += 1;
         return;
@@ -296,7 +310,10 @@ fn meta(ctx: *Context, p: []const u8) !void {
 }
 
 // parses srcpath, resolves refs and portals and writes everything to w
-fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8) !void {
+fn inject(allocator: std.mem.Allocator, w: *std.Io.Writer, srcpath: []const u8) !void {
+    var arena = std.heap.ArenaAllocator.init(allocator);
+    defer arena.deinit();
+
     const inc = std.fs.cwd().openFile(srcpath, .{ .mode = .read_only }) catch |err| {
         if (err == error.FileNotFound)
             log.warn("Missing {s} include.", .{srcpath});
@@ -305,30 +322,27 @@ fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8
     };
     defer inc.close();
 
-    var buf_writer = std.io.bufferedWriter(w);
-    var out_stream = buf_writer.writer();
+    var buffer: [1024]u8 = undefined;
+    var r = inc.readerStreaming(&buffer);
 
-    var buf_reader = std.io.bufferedReader(inc.reader());
-    var in_stream = buf_reader.reader();
+    var chunkw = std.Io.Writer.Allocating.init(arena.allocator());
+    defer chunkw.deinit();
 
-    var arena = std.heap.ArenaAllocator.init(allocator);
-    defer arena.deinit();
+    while (true) {
+        defer chunkw.clearRetainingCapacity(); // reset chunk
+
+        _ = r.interface.streamDelimiter(&chunkw.writer, '\n') catch |err|
+            if (err == error.EndOfStream) break
+            else return err;
 
-    while (in_stream.readUntilDelimiterOrEofAlloc(
-        arena.allocator(),
-        '\n',
-        buf_reader.buf.len,
-    ) catch {
-        @panic("Failed to read from stream");
-    }) |chunk_| {
-        defer _ = arena.reset(.free_all);
+        _ = r.interface.toss(1); // skip newline delimiter
 
-        var chunk = chunk_;
+        var chunk = chunkw.written();
         templating: while (true) {
             if (std.mem.indexOfPosLinear(u8, chunk, 0, "{")) |start| {
                 if (std.mem.indexOfPosLinear(u8, chunk, start + 1, "}")) |end| {
-                    try out_stream.writeAll(chunk[0..start]);
-                    template(allocator, out_stream.any(), chunk[start + 1 .. end]) catch |err| switch (err) {
+                    try w.writeAll(chunk[0..start]);
+                    template(allocator, w, chunk[start + 1 .. end]) catch |err| switch (err) {
                         error.FileNotFound => {
                             // log.warn("ref {s} not found", .{chunk[start + 1 .. end]});
                             // trim already written chunk and exit templating
@@ -342,16 +356,16 @@ fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8
             } else break :templating;
         }
 
-        try out_stream.writeAll(chunk);
-        try out_stream.writeByte('\n');
-        try buf_writer.flush();
+        try w.writeAll(chunk);
+        try w.writeByte('\n');
+        try w.flush();
     }
 
-    try buf_writer.flush();
+    try w.flush();
 }
 
 // implements various reference types that can be used in .htm templates
-fn template(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
+fn template(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void {
     switch (refname[0]) {
         '/' => return try portal(allocator, w, refname[1..], false),
         '$' => return try ref_link(allocator, w, refname[1..]),
@@ -393,7 +407,7 @@ const Page = struct {
     }
 };
 
-fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8, insert_heading: bool) anyerror!void {
+fn portal(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8, insert_heading: bool) anyerror!void {
     const page = try Page.from_ref(allocator, refname);
     defer page.deinit();
 
@@ -412,7 +426,7 @@ fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8
     // XXX: track ref count?
 }
 
-fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
+fn ref(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void {
     const page = try Page.from_ref(allocator, refname);
     defer page.deinit();
 
@@ -427,14 +441,14 @@ fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) a
     // XXX: track ref count?
 }
 
-fn ref_link(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
+fn ref_link(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void {
     const page = try Page.from_ref(allocator, refname);
     defer page.deinit();
 
     try w.print("/{s}{s}", .{ page.html, page.anchor });
 }
 
-fn ref_name(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void {
+fn ref_name(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void {
     const page = try Page.from_ref(allocator, refname);
     defer page.deinit();