Skip to content

Instantly share code, notes, and snippets.

@mikdusan
Created March 25, 2024 17:07
Show Gist options
  • Save mikdusan/3f996e61e1ab09fc26e6b5e55a9d3ae8 to your computer and use it in GitHub Desktop.
Save mikdusan/3f996e61e1ab09fc26e6b5e55a9d3ae8 to your computer and use it in GitHub Desktop.
Zig pipelines with a ruby-like flexible interface for closes, redirects, pipes, symbolic names, files-by-paths, etc.
test "pipeline" {
// SILLY PIPELINE EXAMPLE
//
// cat /etc/passwd | (code-filter) | sort > /tmp/out.txt
// |-- child[0] ---| |---- child[1] -----|
//
// note: not convinced splitting ChildBuilder/ChildProcess is ideal
var builder = .{
try ChildBuilder.init(testing.allocator),
try ChildBuilder.init(testing.allocator),
};
defer builder[0].deinit();
defer builder[1].deinit();
try builder[0].addArgs(&.{"cat", "/etc/passwd"});
try builder[1].addArgs(&.{"sort"});
try builder[1].redirectEndpointTo(.stdout, .{ .create, "/tmp/out.txt" });
const pipe_end = .{
try builder[0].makeEndpointPipe(.stdout, .output),
try builder[1].makeEndpointPipe(.stdin, .input),
};
var pipe_end_open: [2]bool = .{ true, true };
defer if (pipe_end_open[0]) pipe_end[0].close();
defer if (pipe_end_open[1]) pipe_end[1].close();
var child = .{
try builder[0].spawn(testing.allocator),
try builder[1].spawn(testing.allocator),
};
defer child[0].deinit();
defer child[1].deinit();
try filter(pipe_end[0], pipe_end[1]);
pipe_end[0].close();
pipe_end_open[0] = false;
pipe_end[1].close();
pipe_end_open[1] = false;
const wr = .{
try child[0].wait(.{}),
try child[1].wait(.{}),
};
try testing.expect(wr[0] == .exit);
try testing.expectEqual(wr[0].exit, 0);
try testing.expect(wr[1] == .exit);
try testing.expectEqual(wr[1].exit, 0);
}
fn filter(in: std.fs.File, out: std.fs.File) !void {
const r = in.reader();
const w = out.writer();
while (true) {
const b = r.readByte() catch break;
try w.writeByte(if (b == ':') '_' else b);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment