polls on atproto
pollz.waow.tech
atproto
zig
1# zig 0.15 notes
2
3reference for zig 0.15 patterns used in the backend.
4
5## breaking changes from 0.14
6
7### json.stringify → json.fmt
8```zig
9// old: json.stringify(value, .{}, writer);
10// new: use json.fmt formatter
11try buffer.print(allocator, "{f}", .{json.fmt(value, .{})});
12```
13
14### std.ArrayList is unmanaged by default
15```zig
16// old 0.14 style:
17var list = std.ArrayList(u8).init(allocator);
18try list.appendSlice("hello");
19list.deinit();
20
21// new 0.15 style:
22var list: std.ArrayList(u8) = .{};
23try list.appendSlice(allocator, "hello");
24list.deinit(allocator);
25```
26
27### std.time.sleep removed
28```zig
29// use posix.nanosleep instead
30std.posix.nanosleep(seconds, nanoseconds);
31```
32
33### std.Uri.percentDecode → percentDecodeInPlace
34```zig
35// copy to mutable buffer first, then decode in place
36const uri_buf = try alloc.dupe(u8, uri_encoded);
37const uri = std.Uri.percentDecodeInPlace(uri_buf);
38```
39
40## http server patterns
41
42### net.Stream → http.Server
43```zig
44var read_buffer: [8192]u8 = undefined;
45var write_buffer: [8192]u8 = undefined;
46
47var reader = conn.stream.reader(&read_buffer);
48var writer = conn.stream.writer(&write_buffer);
49
50var server = http.Server.init(reader.interface(), &writer.interface);
51```
52
53### responding to requests
54```zig
55try request.respond(body, .{
56 .status = .ok,
57 .extra_headers = &.{
58 .{ .name = "content-type", .value = "application/json" },
59 },
60});
61```
62
63## websocket client (karlseguin/websocket.zig)
64
65```zig
66const websocket = @import("websocket");
67
68var client = try websocket.Client.init(allocator, .{
69 .host = "example.com",
70 .port = 443,
71 .tls = true,
72});
73defer client.deinit();
74
75// Host header must be provided manually
76client.handshake("/path", .{ .headers = "Host: example.com\r\n" }) catch |err| {
77 // handle error
78};
79
80// handler must have serverMessage(self, data) function
81var handler = MyHandler{};
82try client.readLoop(&handler);
83```
84
85## sqlite patterns (zqlite)
86
87### prepared statements with bind
88```zig
89var stmt = conn.prepare("SELECT * FROM votes WHERE uri = ?") catch return;
90defer stmt.deinit();
91
92const row = stmt.bind(.{uri}).step() catch return;
93if (row) |r| {
94 const subject = r[0].?.text;
95 // ...
96}
97```
98
99### upsert with ON CONFLICT
100```zig
101conn.exec(
102 \\INSERT INTO votes (uri, subject, option, voter, created_at)
103 \\VALUES (?, ?, ?, ?, ?)
104 \\ON CONFLICT(subject, voter) DO UPDATE SET
105 \\ uri = excluded.uri,
106 \\ option = excluded.option,
107 \\ created_at = excluded.created_at
108 \\WHERE excluded.created_at > votes.created_at OR votes.created_at IS NULL
109, .{ uri, subject, option, voter, created_at }) catch |err| {
110 // handle error
111};
112```
113
114## build.zig.zon
115
116```zig
117.{
118 .name = .pollz,
119 .version = "0.0.0",
120 .fingerprint = 0x..., // required in 0.15
121 .dependencies = .{
122 .zqlite = .{ ... },
123 .websocket = .{ ... },
124 },
125}
126```