1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2026-01-29 09:06:58 +00:00

Update to Zig 0.16.0-dev (master) compatibility

Adapt codebase to breaking API changes in Zig 0.16.0-dev:

std.Io introduction:
- std.io namespace renamed to std.Io (capitalization)
- std.http.Client now requires io field
- Create std.Io.Threaded at entry points, pass io to functions
- Use std.Io.Writer.fixed() for fixed buffer writers
- Use std.Io.Dir.cwd().access(io, ...) for file access checks

Sleep API:
- std.Thread.sleep / std.time.sleep removed
- Use std.posix.nanosleep(seconds, nanoseconds) instead

JSON API:
- std.json.stringify() -> std.json.Stringify.value()

Time API:
- std.time.nanoTimestamp() removed
- Use std.time.Instant.now() with .since() for durations

File API:
- readFileAlloc parameter order changed, uses std.Io.Limit

Debug API:
- std.debug.writeStackTrace signature changed (removed debugInfo)
- Capture traces by pointer with |*trace| pattern

Refactored Io pattern in tests/examples to create Threaded once
at entry points and pass io: std.Io to helper functions, following
Zig's new convention of treating Io like allocators.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
renerocksai 2025-12-06 16:11:10 +01:00
parent 76679f308c
commit a0f67ffc6e
No known key found for this signature in database
GPG key ID: 28E7827C1F1B174C
15 changed files with 131 additions and 65 deletions

1
.oms Normal file
View file

@ -0,0 +1 @@
PROJECT=rene.zap

View file

@ -57,7 +57,7 @@ const SimpleEndpoint = struct {
.{ context.db_connection, e.some_data, arena.ptr, thread_id },
);
try r.sendBody(response_text);
std.Thread.sleep(std.time.ns_per_ms * 300);
std.posix.nanosleep(0, std.time.ns_per_ms * 300);
}
};

View file

@ -16,8 +16,8 @@ pub const std_options: std.Options = .{
};
// We send ourselves a request with a cookie
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a };
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
_ = try http_client.fetch(.{
@ -29,8 +29,8 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
});
}
fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, url });
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url });
}
// here we go
@ -118,7 +118,11 @@ pub fn main() !void {
try listener.listen();
std.log.info("\n\nTerminate with CTRL+C", .{});
const thread = try makeRequestThread(allocator, "http://127.0.0.1:3000");
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(allocator, io, "http://127.0.0.1:3000");
defer thread.join();
zap.start(.{
.threads = 1,

View file

@ -16,8 +16,8 @@ pub const std_options: std.Options = .{
};
// We send ourselves a request
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a };
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
const response = try http_client.fetch(.{
@ -31,8 +31,8 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
}
}
fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, url });
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url });
}
// here we go
@ -138,7 +138,11 @@ pub fn main() !void {
try listener.listen();
std.log.info("\n\nTerminate with CTRL+C or by sending query param terminate=true", .{});
const thread = try makeRequestThread(allocator, "http://127.0.0.1:3000/?one=1&two=2&string=hello+world&float=6.28&bool=true");
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(allocator, io, "http://127.0.0.1:3000/?one=1&two=2&string=hello+world&float=6.28&bool=true");
defer thread.join();
zap.start(.{
.threads = 1,

View file

@ -39,14 +39,21 @@ fn help_and_exit(filename: []const u8, err: anyerror) void {
std.process.exit(1);
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
var threaded = std.Io.Threaded.init(gpa.allocator());
defer threaded.deinit();
const io = threaded.io();
const CERT_FILE = "mycert.pem";
const KEY_FILE = "mykey.pem";
std.fs.cwd().access(CERT_FILE, .{}) catch |err| {
std.Io.Dir.cwd().access(io, CERT_FILE, .{}) catch |err| {
help_and_exit(CERT_FILE, err);
};
std.fs.cwd().access(KEY_FILE, .{}) catch |err| {
std.Io.Dir.cwd().access(io, KEY_FILE, .{}) catch |err| {
help_and_exit(KEY_FILE, err);
};

View file

@ -589,7 +589,8 @@ pub fn UserPassSession(comptime Lookup: type, comptime lockedPwLookups: bool) ty
hasher.update(username);
hasher.update(password);
var buf: [16]u8 = undefined;
const time_nano = std.time.nanoTimestamp();
const instant = std.time.Instant.now() catch unreachable;
const time_nano: i128 = @as(i128, instant.timestamp.sec) * std.time.ns_per_s + instant.timestamp.nsec;
const timestampHex = try std.fmt.bufPrint(&buf, "{0x}", .{time_nano});
hasher.update(timestampHex);

View file

@ -354,13 +354,12 @@ pub fn _internal_sendError(self: *const Request, err: anyerror, err_trace: ?std.
// TODO: let's hope 20k is enough. Maybe just really allocate here
self.h.*.status = errorcode_num;
var buf: [20 * 1024]u8 = undefined;
var writer = std.io.Writer.fixed(&buf);
var writer = std.Io.Writer.fixed(&buf);
try writer.print("ERROR: {any}\n\n", .{err});
if (err_trace) |trace| {
const debugInfo = try std.debug.getSelfDebugInfo();
const ttyConfig: std.io.tty.Config = .no_color;
try std.debug.writeStackTrace(trace, &writer, debugInfo, ttyConfig);
if (err_trace) |*trace| {
const ttyConfig: std.Io.tty.Config = .no_color;
try std.debug.writeStackTrace(trace, &writer, ttyConfig);
}
try self.sendBody(writer.buffered());

View file

@ -110,8 +110,8 @@ const ClientAuthReqHeaderFields = struct {
token: []const u8,
};
fn makeRequest(a: std.mem.Allocator, url: []const u8, auth: ?ClientAuthReqHeaderFields) !void {
var http_client: std.http.Client = .{ .allocator = a };
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8, auth: ?ClientAuthReqHeaderFields) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
var auth_buf: [256]u8 = undefined;
@ -143,8 +143,8 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8, auth: ?ClientAuthReqHeader
zap.stop();
}
fn makeRequestThread(a: std.mem.Allocator, url: []const u8, auth: ?ClientAuthReqHeaderFields) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, url, auth });
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8, auth: ?ClientAuthReqHeaderFields) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url, auth });
}
pub const Endpoint = struct {
@ -154,7 +154,7 @@ pub const Endpoint = struct {
pub fn get(_: *Endpoint, r: zap.Request) !void {
r.sendBody(HTTP_RESPONSE) catch return;
received_response = HTTP_RESPONSE;
std.Thread.sleep(1 * std.time.ns_per_s);
std.posix.nanosleep(1, 0);
zap.stop();
}
@ -162,7 +162,7 @@ pub const Endpoint = struct {
r.setStatus(.unauthorized);
r.sendBody("UNAUTHORIZED ACCESS") catch return;
received_response = "UNAUTHORIZED";
std.Thread.sleep(1 * std.time.ns_per_s);
std.posix.nanosleep(1, 0);
zap.stop();
}
};
@ -205,7 +205,11 @@ test "BearerAuthSingle authenticateRequest OK" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3001/test", .{ .auth = .Bearer, .token = token });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3001/test", .{ .auth = .Bearer, .token = token });
defer thread.join();
// start worker threads
@ -258,7 +262,11 @@ test "BearerAuthSingle authenticateRequest test-unauthorized" {
try listener.listen();
const thread = try makeRequestThread(a, "http://127.0.0.1:3002/test", .{ .auth = .Bearer, .token = "invalid" });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3002/test", .{ .auth = .Bearer, .token = "invalid" });
defer thread.join();
// start worker threads
@ -305,7 +313,11 @@ test "BearerAuthMulti authenticateRequest OK" {
try listener.listen();
const thread = try makeRequestThread(a, "http://127.0.0.1:3003/test", .{ .auth = .Bearer, .token = token });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3003/test", .{ .auth = .Bearer, .token = token });
defer thread.join();
// start worker threads
@ -352,7 +364,11 @@ test "BearerAuthMulti authenticateRequest test-unauthorized" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3004/test", .{ .auth = .Bearer, .token = "invalid" });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3004/test", .{ .auth = .Bearer, .token = "invalid" });
defer thread.join();
// start worker threads
@ -404,7 +420,11 @@ test "BasicAuth Token68 authenticateRequest" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3005/test", .{ .auth = .Basic, .token = token });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3005/test", .{ .auth = .Basic, .token = token });
defer thread.join();
// start worker threads
@ -456,7 +476,11 @@ test "BasicAuth Token68 authenticateRequest test-unauthorized" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3006/test", .{ .auth = .Basic, .token = "invalid" });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3006/test", .{ .auth = .Basic, .token = "invalid" });
defer thread.join();
// start worker threads
@ -518,7 +542,11 @@ test "BasicAuth UserPass authenticateRequest" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3007/test", .{ .auth = .Basic, .token = encoded });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3007/test", .{ .auth = .Basic, .token = encoded });
defer thread.join();
// start worker threads
@ -583,7 +611,11 @@ test "BasicAuth UserPass authenticateRequest test-unauthorized" {
listener.listen() catch {};
const thread = try makeRequestThread(a, "http://127.0.0.1:3008/test", .{ .auth = .Basic, .token = "invalid" });
var threaded = std.Io.Threaded.init(a);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(a, io, "http://127.0.0.1:3008/test", .{ .auth = .Basic, .token = "invalid" });
defer thread.join();
// start worker threads

View file

@ -9,8 +9,8 @@ pub const std_options: std.Options = .{
},
};
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a };
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
_ = try http_client.fetch(.{
@ -20,8 +20,8 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
zap.stop();
}
fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, url });
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url });
}
test "http parameters" {
@ -74,7 +74,11 @@ test "http parameters" {
);
try listener.listen();
const thread = try makeRequestThread(allocator, "http://127.0.0.1:3010/?one=1&two=2&string=hello+world&float=6.28&bool=true");
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(allocator, io, "http://127.0.0.1:3010/?one=1&two=2&string=hello+world&float=6.28&bool=true");
defer thread.join();
zap.start(.{
.threads = 1,

View file

@ -18,8 +18,8 @@ const EXPECTED_FILENAME = "myfile.txt";
var test_error: ?anyerror = null;
fn makeRequest(allocator: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = allocator };
fn makeRequest(allocator: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = allocator, .io = io };
defer http_client.deinit();
const payload_wrong_line_ending = try std.fmt.allocPrint(allocator,
@ -117,7 +117,11 @@ test "recv file" {
);
try listener.listen();
const t1 = try std.Thread.spawn(.{}, makeRequest, .{ allocator, "http://127.0.0.1:3020" });
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const t1 = try std.Thread.spawn(.{}, makeRequest, .{ allocator, io, "http://127.0.0.1:3020" });
defer t1.join();
zap.start(.{

View file

@ -17,8 +17,8 @@ const EXPECTED_FILENAME = "myfile.txt";
var test_error: ?anyerror = null;
fn makeRequest(allocator: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = allocator };
fn makeRequest(allocator: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = allocator, .io = io };
defer http_client.deinit();
const payload_wrong_line_ending = try std.fmt.allocPrint(allocator,
@ -115,7 +115,11 @@ test "recv file" {
);
try listener.listen();
const t1 = try std.Thread.spawn(.{}, makeRequest, .{ allocator, "http://127.0.0.1:3030" });
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const t1 = try std.Thread.spawn(.{}, makeRequest, .{ allocator, io, "http://127.0.0.1:3030" });
defer t1.join();
zap.start(.{

View file

@ -14,11 +14,11 @@ var read_len: ?usize = null;
const testfile = @embedFile("testfile.txt");
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a };
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
var response_writer = std.io.Writer.Allocating.init(a);
var response_writer = std.Io.Writer.Allocating.init(a);
defer response_writer.deinit();
_ = try http_client.fetch(.{
@ -33,8 +33,8 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
zap.stop();
}
fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, url });
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url });
}
pub fn on_request(r: zap.Request) !void {
r.sendFile("src/tests/testfile.txt") catch unreachable;
@ -55,7 +55,11 @@ test "send file" {
);
try listener.listen();
const thread = try makeRequestThread(allocator, "http://127.0.0.1:3040/?file=src/tests/testfile.txt");
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(allocator, io, "http://127.0.0.1:3040/?file=src/tests/testfile.txt");
defer thread.join();
zap.start(.{
.threads = 1,

View file

@ -77,7 +77,7 @@ pub fn stringifyBuf(
value: anytype,
options: std.json.Stringify.Options,
) ![]const u8 {
var w: std.io.Writer = .fixed(buffer);
var w = std.Io.Writer.fixed(buffer);
if (std.json.Stringify.value(value, options, &w)) {
return w.buffered();
} else |err| { // error

View file

@ -288,7 +288,7 @@ pub const HttpListener = struct {
// in debug2 and debug3 of hello example
// std.debug.print("X\n", .{});
// TODO: still happening?
std.Thread.sleep(500 * std.time.ns_per_ms);
std.posix.nanosleep(0, 500 * std.time.ns_per_ms);
var portbuf: [100]u8 = undefined;
const printed_port = try std.fmt.bufPrintZ(&portbuf, "{d}", .{self.settings.port});
@ -364,7 +364,7 @@ pub const LowLevel = struct {
// in debug2 and debug3 of hello example
// std.debug.print("X\n", .{});
// TODO: still happening?
std.Thread.sleep(500 * std.time.ns_per_ms);
std.posix.nanosleep(0, 500 * std.time.ns_per_ms);
if (fio.http_listen(port, interface, x) == -1) {
return error.ListenError;

View file

@ -57,7 +57,10 @@ pub fn main() !void {
}
if (std.mem.eql(u8, command, "announce")) {
return command_announce(gpa, tagname);
var threaded = std.Io.Threaded.init(gpa);
defer threaded.deinit();
const io = threaded.io();
return command_announce(gpa, io, tagname);
}
if (std.mem.eql(u8, command, "release-notes")) {
@ -121,10 +124,9 @@ fn renderTemplate(allocator: std.mem.Allocator, template: []const u8, substitute
return try std.mem.replaceOwned(u8, allocator, s1, "{annotation}", the_anno);
}
fn sendToDiscordPart(allocator: std.mem.Allocator, url: []const u8, message_json: []const u8) !void {
fn sendToDiscordPart(allocator: std.mem.Allocator, io: std.Io, url: []const u8, message_json: []const u8) !void {
// client
var http_client: std.http.Client = .{ .allocator = allocator };
var http_client: std.http.Client = .{ .allocator = allocator, .io = io };
const response = try http_client.fetch(.{
.location = .{ .url = url },
@ -139,18 +141,18 @@ fn sendToDiscordPart(allocator: std.mem.Allocator, url: []const u8, message_json
}
}
fn sendToDiscord(allocator: std.mem.Allocator, url: []const u8, message: []const u8) !void {
fn sendToDiscord(allocator: std.mem.Allocator, io: std.Io, url: []const u8, message: []const u8) !void {
// json payload
// max size: 100kB
const buf: []u8 = try allocator.alloc(u8, 100 * 1024);
defer allocator.free(buf);
var w: std.io.Writer = .fixed(buf);
var w = std.Io.Writer.fixed(buf);
try std.json.Stringify.value(.{ .content = message }, .{}, &w);
const string = w.buffered();
// We need to split shit into max 2000 characters
if (string.len < 1999) {
try sendToDiscordPart(allocator, url, string);
try sendToDiscordPart(allocator, io, url, string);
return;
}
@ -263,18 +265,18 @@ fn sendToDiscord(allocator: std.mem.Allocator, url: []const u8, message: []const
const desc = chunks.items[it];
const part = message[desc.from..desc.to];
var ww: std.io.Writer = .fixed(buf);
var ww = std.Io.Writer.fixed(buf);
try std.json.Stringify.value(.{ .content = part }, .{}, &ww);
const part_string = ww.buffered();
std.debug.print("SENDING PART {d} / {d}: ... ", .{ it, chunks.items.len });
try sendToDiscordPart(allocator, url, part_string);
try sendToDiscordPart(allocator, io, url, part_string);
std.debug.print("done!\n", .{});
it += 1;
}
}
fn command_announce(allocator: std.mem.Allocator, tag: []const u8) !void {
fn command_announce(allocator: std.mem.Allocator, io: std.Io, tag: []const u8) !void {
const annotation = try get_tag_annotation(allocator, tag);
defer allocator.free(annotation);
@ -287,7 +289,7 @@ fn command_announce(allocator: std.mem.Allocator, tag: []const u8) !void {
defer allocator.free(announcement);
const url = try std.process.getEnvVarOwned(allocator, "WEBHOOK_URL");
defer allocator.free(url);
sendToDiscord(allocator, url, announcement) catch |err| {
sendToDiscord(allocator, io, url, announcement) catch |err| {
std.debug.print("HTTP ERROR: {any}\n", .{err});
std.process.exit(1);
};
@ -320,7 +322,7 @@ fn command_update_readme(allocator: std.mem.Allocator, tag: []const u8) !void {
defer allocator.free(update_part);
// read the readme
const readme = try std.fs.cwd().readFileAlloc(allocator, README_PATH, README_MAX_SIZE);
const readme = try std.fs.cwd().readFileAlloc(README_PATH, allocator, std.Io.Limit.limited(README_MAX_SIZE));
defer allocator.free(readme);
var output_file = try std.fs.cwd().createFile(README_PATH, .{});