about things
0.16 migration notes#
verified with zig-aarch64-macos-0.16.0-dev.2296+fd3657bf8
high-impact changes#
- std.net removed - networking now via
Io.net - std.crypto.random removed - randomness now via
io.random() - std.Thread.Pool removed - use
Io.GroupwithIo.Threaded - posix.shutdown removed - use
std.c.shutdown(fd, how) - posix.getrandom removed - use
io.random()
these require significant refactoring as they move to the Io-based paradigm.
build.zig changes#
linkLibC() removed. use module options instead:
// 0.15
const exe = b.addExecutable(.{...});
exe.linkLibC();
// 0.16
const exe = b.addExecutable(.{
.name = "myapp",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.link_libc = true, // here
}),
});
package hashes#
0.16 calculates hashes differently. compiler will tell you the correct hash.
removed APIs#
std.time.timestamp() / milliTimestamp()#
use libc directly:
const c = std.c;
pub fn timestamp() i64 {
var tv: c.timeval = undefined;
_ = c.gettimeofday(&tv, null);
return tv.sec;
}
pub fn milliTimestamp() i64 {
var tv: c.timeval = undefined;
_ = c.gettimeofday(&tv, null);
return @as(i64, tv.sec) * 1000 + @divTrunc(@as(i64, tv.usec), 1000);
}
std.Thread.sleep()#
use libc nanosleep:
pub fn sleep(ns: u64) void {
const secs = ns / std.time.ns_per_s;
const nsecs = ns % std.time.ns_per_s;
var ts: std.c.timespec = .{
.sec = @intCast(secs),
.nsec = @intCast(nsecs),
};
_ = std.c.nanosleep(&ts, null);
}
std.posix.getenv()#
use std.c.getenv() with std.mem.span():
// 0.15
const val = std.posix.getenv("FOO") orelse "default";
// 0.16 - returns [*:0]const u8, not slice
const val = if (std.c.getenv("FOO")) |p| std.mem.span(p) else "default";
@Type builtin#
removed. use specific type builtins:
// 0.15
const Args = @Type(.{ .@"struct" = .{ .is_tuple = true, ... } });
// 0.16
const Args = @Tuple(&field_types);
// or @Struct(...) for non-tuples
posix.shutdown#
use libc directly:
// 0.15
posix.shutdown(fd, .recv) catch {};
// 0.16
_ = std.c.shutdown(fd, 0); // SHUT_RD = 0, SHUT_WR = 1, SHUT_RDWR = 2
std.testing.expectEqual#
argument order changed (minor but affects all tests):
// 0.15
try std.testing.expectEqual(@as(@TypeOf(actual), expected), actual);
// 0.16 - simpler, expected comes first naturally
try std.testing.expectEqual(expected, actual);
networking#
std.net is gone. use Io.net:
const Io = std.Io;
const net = Io.net;
// connecting to a host
pub fn connect(io: Io, host: []const u8, port: u16) !net.Stream {
const host_name = try net.HostName.init(host);
return host_name.connect(io, port, .{});
}
note: Io.net.Stream no longer has direct read/writeAll methods.
you need to create Stream.Reader or Stream.Writer wrappers:
// reading from stream requires a Reader wrapper
pub fn readFromStream(stream: net.Stream, io: Io, buffer: []u8) !usize {
var reader = net.Stream.Reader.init(stream, io, buffer);
// use reader.interface for reading
return reader.interface.read(buffer);
}
net.Address → net.IpAddress:
// 0.15
const addr = std.net.Address.parseIp("127.0.0.1", 8080);
// 0.16
const addr = Io.net.IpAddress.parse("127.0.0.1", 8080);
randomness#
std.crypto.random removed. use io.random():
// 0.15
var bytes: [16]u8 = undefined;
std.crypto.random.bytes(&bytes);
// 0.16 - io.random() returns typed value directly
const io = std.Options.debug_io;
const bytes: [16]u8 = io.random(); // returns [16]u8 directly
const seed: u64 = io.random(); // returns u64 directly
file I/O#
file ops now take io: Io parameter. get default io from std.Options.debug_io:
const std = @import("std");
const Io = std.Io;
pub fn readFile(path: []const u8) ![]u8 {
const io = std.Options.debug_io;
const file = try Io.Dir.openFileAbsolute(io, path, .{});
defer file.close(io);
var buf: [4096]u8 = undefined;
const n = try file.readPositional(io, &.{&buf}, 0);
return buf[0..n];
}
pub fn writeFile(path: []const u8, data: []const u8) !void {
const io = std.Options.debug_io;
const file = try Io.Dir.createFileAbsolute(io, path, .{});
defer file.close(io);
try file.writeStreamingAll(io, data);
}