I was trying to create a simple tcp server in Zig using the new Io libs, but i got confused with the new reader/writer api. I’m not sure why writer.interface() doesn’t work here.
const std = @import("std");
pub fn main() !void {
const addr = try std.net.Address.resolveIp("0.0.0.0", 8080);
var server = try std.net.Address.listen(addr, .{});
defer server.deinit();
while (true) {
var conn = try server.accept();
defer conn.stream.close();
var buf: [1024]u8 = undefined;
var reader = conn.stream.reader(&buf);
var writer = conn.stream.writer(&.{});
// Works
const msg = try std.Io.Reader.takeDelimiterInclusive(reader.interface(), '\n');
// Works
const msg = try std.Io.Reader.takeDelimiterInclusive(&reader.file_writer.interface, '\n');
// Compile error:
try std.Io.Writer.writeAll(writer.interface(), msg);
// Works
try std.Io.Writer.writeAll(&writer.file_writer.interface, msg);
}
}
The error compilation error:
error: type 'Io.Writer' not a function
try std.Io.Writer.writeAll(writer.interface(), msg);
~~~~~~^~~~~~~~~~
Im on zig 0.15.2
If there are any good writeups on how the new Io system is structured, i’d really appreciate it.
In this case, the stream.writer() returns a struct in which interface is a field. It is not a function like stream.reader().inferface(). So you would not call interface because it is a field, not a function. This is odd, because it is not symmetrical, which is more of what one would expect. So the StreamReader has a function to get the std.Io.Reader interface, and the StreamWriter, has the interface as a direct field.
Also, you can use functions directly from the interface instead of having to do the std.Io.Writer.writeAll call.
var conn = try server.accept();
defer conn.stream.close();
var buf: [1024]u8 = undefined;
var reader = conn.stream.reader(&buf);
var writer = conn.stream.writer(&.{});
// Works
const msg = try reader.interface().takeDelimiterInclusive('\n');
// Works
const msg = try reader.file_writer.interface.takeDelimiterInclusive('\n');
// Works
try writer.interface.writeAll(msg);
// Works
try writer.file_writer.interface.writeAll(msg);
I’m not sure, but looking at the code, I think it has to do with target differences. std.net.Stream.Reader on Windows has different fields than on Linux or Macos. In order to hide this difference, they expose the method to get the right field regardless of host OS.
Writer is different. It has the same field on all OSs and so it does not need to abstract that behind a function.
I think another reason may be that this is all being refactored in 0.16, so this may be a temporary asymmetry.
This seems to be the case looking at the std docs for master.
This shows that the reader will now have a uniform setup across OSs