about things
1# 0.16 migration notes
2
3verified with `zig-aarch64-macos-0.16.0-dev.2296+fd3657bf8`
4
5## high-impact changes
6
7- **std.net removed** - networking now via `Io.net`
8- **std.crypto.random removed** - randomness now via `io.random()`
9- **std.Thread.Pool removed** - use `Io.Group` with `Io.Threaded`
10- **posix.shutdown removed** - use `std.c.shutdown(fd, how)`
11- **posix.getrandom removed** - use `io.random()`
12
13these require significant refactoring as they move to the Io-based paradigm.
14
15## build.zig changes
16
17`linkLibC()` removed. use module options instead:
18
19```zig
20// 0.15
21const exe = b.addExecutable(.{...});
22exe.linkLibC();
23
24// 0.16
25const exe = b.addExecutable(.{
26 .name = "myapp",
27 .root_module = b.createModule(.{
28 .root_source_file = b.path("src/main.zig"),
29 .target = target,
30 .optimize = optimize,
31 .link_libc = true, // here
32 }),
33});
34```
35
36## package hashes
37
380.16 calculates hashes differently. compiler will tell you the correct hash.
39
40## removed APIs
41
42### std.time.timestamp() / milliTimestamp()
43
44use libc directly:
45
46```zig
47const c = std.c;
48
49pub fn timestamp() i64 {
50 var tv: c.timeval = undefined;
51 _ = c.gettimeofday(&tv, null);
52 return tv.sec;
53}
54
55pub fn milliTimestamp() i64 {
56 var tv: c.timeval = undefined;
57 _ = c.gettimeofday(&tv, null);
58 return @as(i64, tv.sec) * 1000 + @divTrunc(@as(i64, tv.usec), 1000);
59}
60```
61
62### std.Thread.sleep()
63
64use libc nanosleep:
65
66```zig
67pub fn sleep(ns: u64) void {
68 const secs = ns / std.time.ns_per_s;
69 const nsecs = ns % std.time.ns_per_s;
70 var ts: std.c.timespec = .{
71 .sec = @intCast(secs),
72 .nsec = @intCast(nsecs),
73 };
74 _ = std.c.nanosleep(&ts, null);
75}
76```
77
78### std.posix.getenv()
79
80use `std.c.getenv()` with `std.mem.span()`:
81
82```zig
83// 0.15
84const val = std.posix.getenv("FOO") orelse "default";
85
86// 0.16 - returns [*:0]const u8, not slice
87const val = if (std.c.getenv("FOO")) |p| std.mem.span(p) else "default";
88```
89
90### @Type builtin
91
92removed. use specific type builtins:
93
94```zig
95// 0.15
96const Args = @Type(.{ .@"struct" = .{ .is_tuple = true, ... } });
97
98// 0.16
99const Args = @Tuple(&field_types);
100// or @Struct(...) for non-tuples
101```
102
103### posix.shutdown
104
105use libc directly:
106
107```zig
108// 0.15
109posix.shutdown(fd, .recv) catch {};
110
111// 0.16
112_ = std.c.shutdown(fd, 0); // SHUT_RD = 0, SHUT_WR = 1, SHUT_RDWR = 2
113```
114
115### std.testing.expectEqual
116
117argument order changed (minor but affects all tests):
118
119```zig
120// 0.15
121try std.testing.expectEqual(@as(@TypeOf(actual), expected), actual);
122
123// 0.16 - simpler, expected comes first naturally
124try std.testing.expectEqual(expected, actual);
125```
126
127## networking
128
129`std.net` is gone. use `Io.net`:
130
131```zig
132const Io = std.Io;
133const net = Io.net;
134
135// connecting to a host
136pub fn connect(io: Io, host: []const u8, port: u16) !net.Stream {
137 const host_name = try net.HostName.init(host);
138 return host_name.connect(io, port, .{});
139}
140```
141
142**note**: `Io.net.Stream` no longer has direct `read`/`writeAll` methods.
143you need to create `Stream.Reader` or `Stream.Writer` wrappers:
144
145```zig
146// reading from stream requires a Reader wrapper
147pub fn readFromStream(stream: net.Stream, io: Io, buffer: []u8) !usize {
148 var reader = net.Stream.Reader.init(stream, io, buffer);
149 // use reader.interface for reading
150 return reader.interface.read(buffer);
151}
152```
153
154`net.Address` → `net.IpAddress`:
155```zig
156// 0.15
157const addr = std.net.Address.parseIp("127.0.0.1", 8080);
158
159// 0.16
160const addr = Io.net.IpAddress.parse("127.0.0.1", 8080);
161```
162
163## randomness
164
165`std.crypto.random` removed. use `io.random()`:
166
167```zig
168// 0.15
169var bytes: [16]u8 = undefined;
170std.crypto.random.bytes(&bytes);
171
172// 0.16 - io.random() returns typed value directly
173const io = std.Options.debug_io;
174const bytes: [16]u8 = io.random(); // returns [16]u8 directly
175const seed: u64 = io.random(); // returns u64 directly
176```
177
178## file I/O
179
180file ops now take `io: Io` parameter. get default io from `std.Options.debug_io`:
181
182```zig
183const std = @import("std");
184const Io = std.Io;
185
186pub fn readFile(path: []const u8) ![]u8 {
187 const io = std.Options.debug_io;
188
189 const file = try Io.Dir.openFileAbsolute(io, path, .{});
190 defer file.close(io);
191
192 var buf: [4096]u8 = undefined;
193 const n = try file.readPositional(io, &.{&buf}, 0);
194 return buf[0..n];
195}
196
197pub fn writeFile(path: []const u8, data: []const u8) !void {
198 const io = std.Options.debug_io;
199
200 const file = try Io.Dir.createFileAbsolute(io, path, .{});
201 defer file.close(io);
202
203 try file.writeStreamingAll(io, data);
204}
205```