feature. See also
. The project being documented here (as the example) is the Zig library itself.
main.IoStream
const IoStream = struct
File
Code
const IoStream = struct {
name: []const u8,
intermediate: bool,
source: Source,
pub const IoDirection = enum { input, output };
pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !IoStream {
return .{
.name = switch (source) {
.filename => |filename| filename,
.stdio => switch (io_direction) {
.input => "<stdin>",
.output => "<stdout>",
},
},
.intermediate = false,
.source = try Source.fromIoSource(io, source, io_direction),
};
}
pub fn deinit(self: *IoStream, allocator: Allocator, io: Io) void {
self.source.deinit(allocator, io);
}
pub fn cleanupAfterError(self: *IoStream, io: Io) void {
switch (self.source) {
.file => |file| {
file.close(io);
Io.Dir.cwd().deleteFile(io, self.name) catch {};
},
.stdio, .memory, .closed => return,
}
}
pub const Source = union(enum) {
file: Io.File,
stdio: Io.File,
memory: std.ArrayList(u8),
closed: void,
pub fn fromIoSource(io: Io, source: cli.Options.IoSource, io_direction: IoDirection) !Source {
switch (source) {
.filename => |filename| return .{
.file = switch (io_direction) {
.input => try Io.Dir.cwd().openFile(io, filename, .{ .allow_directory = false }),
.output => try Io.Dir.cwd().createFile(io, filename, .{}),
},
},
.stdio => |file| return .{ .stdio = file },
}
}
pub fn deinit(self: *Source, allocator: Allocator, io: Io) void {
switch (self.*) {
.file => |file| file.close(io),
.stdio => {},
.memory => |*list| list.deinit(allocator),
.closed => {},
}
}
pub const Data = struct {
bytes: []const u8,
needs_free: bool,
pub fn deinit(self: Data, allocator: Allocator) void {
if (self.needs_free) {
allocator.free(self.bytes);
}
}
};
pub fn readAll(self: Source, allocator: Allocator, io: Io) !Data {
return switch (self) {
inline .file, .stdio => |file| .{
.bytes = b: {
var file_reader = file.reader(io, &.{});
break :b try file_reader.interface.allocRemaining(allocator, .unlimited);
},
.needs_free = true,
},
.memory => |list| .{ .bytes = list.items, .needs_free = false },
.closed => unreachable,
};
}
pub const Writer = union(enum) {
file: Io.File.Writer,
allocating: std.Io.Writer.Allocating,
pub const Error = Allocator.Error || Io.File.WriteError;
pub fn interface(this: *@This()) *std.Io.Writer {
return switch (this.*) {
.file => |*fw| &fw.interface,
.allocating => |*a| &a.writer,
};
}
pub fn deinit(this: *@This(), source: *Source) void {
switch (this.*) {
.file => {},
.allocating => |*a| source.memory = a.toArrayList(),
}
this.* = undefined;
}
};
pub fn writer(source: *Source, allocator: Allocator, io: Io, buffer: []u8) Writer {
return switch (source.*) {
.file, .stdio => |file| .{ .file = file.writer(io, buffer) },
.memory => |*list| .{ .allocating = .fromArrayList(allocator, list) },
.closed => unreachable,
};
}
};
}