mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
Zig 0.14 compatibility
This commit is contained in:
committed by
Pierre Tachoire
parent
17d3d620ff
commit
21c9dde858
2
.github/actions/install/action.yml
vendored
2
.github/actions/install/action.yml
vendored
@@ -5,7 +5,7 @@ inputs:
|
|||||||
zig:
|
zig:
|
||||||
description: 'Zig version to install'
|
description: 'Zig version to install'
|
||||||
required: false
|
required: false
|
||||||
default: '0.13.0'
|
default: '0.14.0'
|
||||||
arch:
|
arch:
|
||||||
description: 'CPU arch used to select the v8 lib'
|
description: 'CPU arch used to select the v8 lib'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
2
.github/workflows/zig-fmt.yml
vendored
2
.github/workflows/zig-fmt.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: zig-fmt
|
name: zig-fmt
|
||||||
|
|
||||||
env:
|
env:
|
||||||
ZIG_VERSION: 0.13.0
|
ZIG_VERSION: 0.14.0
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,6 +1,7 @@
|
|||||||
[submodule "vendor/zig-js-runtime"]
|
[submodule "vendor/zig-js-runtime"]
|
||||||
path = vendor/zig-js-runtime
|
path = vendor/zig-js-runtime
|
||||||
url = https://github.com/lightpanda-io/zig-js-runtime.git/
|
url = https://github.com/lightpanda-io/zig-js-runtime.git/
|
||||||
|
branch = zig-0.14
|
||||||
[submodule "vendor/netsurf/libwapcaplet"]
|
[submodule "vendor/netsurf/libwapcaplet"]
|
||||||
path = vendor/netsurf/libwapcaplet
|
path = vendor/netsurf/libwapcaplet
|
||||||
url = https://github.com/lightpanda-io/libwapcaplet.git/
|
url = https://github.com/lightpanda-io/libwapcaplet.git/
|
||||||
@@ -28,3 +29,4 @@
|
|||||||
[submodule "vendor/zig-async-io"]
|
[submodule "vendor/zig-async-io"]
|
||||||
path = vendor/zig-async-io
|
path = vendor/zig-async-io
|
||||||
url = https://github.com/lightpanda-io/zig-async-io.git/
|
url = https://github.com/lightpanda-io/zig-async-io.git/
|
||||||
|
branch = zig-0.14
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:24.04
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
ARG MINISIG=0.12
|
ARG MINISIG=0.12
|
||||||
ARG ZIG=0.13.0
|
ARG ZIG=0.14.0
|
||||||
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
||||||
ARG ARCH=x86_64
|
ARG ARCH=x86_64
|
||||||
ARG V8=11.1.134
|
ARG V8=11.1.134
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ You can also follow the progress of our Javascript support in our dedicated [zig
|
|||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
Lightpanda is written with [Zig](https://ziglang.org/) `0.13.0`. You have to
|
Lightpanda is written with [Zig](https://ziglang.org/) `0.14.0`. You have to
|
||||||
install it with the right version in order to build the project.
|
install it with the right version in order to build the project.
|
||||||
|
|
||||||
Lightpanda also depends on
|
Lightpanda also depends on
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
// compile
|
// compile
|
||||||
const tests = b.addTest(.{
|
const tests = b.addTest(.{
|
||||||
.root_source_file = b.path("src/main_tests.zig"),
|
.root_source_file = b.path("src/main_tests.zig"),
|
||||||
.test_runner = b.path("src/main_tests.zig"),
|
.test_runner = .{ .path = b.path("src/main_tests.zig"), .mode = .simple },
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = mode,
|
.optimize = mode,
|
||||||
});
|
});
|
||||||
@@ -134,7 +134,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
// compile
|
// compile
|
||||||
const unit_tests = b.addTest(.{
|
const unit_tests = b.addTest(.{
|
||||||
.root_source_file = b.path("src/unit_tests.zig"),
|
.root_source_file = b.path("src/unit_tests.zig"),
|
||||||
.test_runner = b.path("src/unit_tests.zig"),
|
.test_runner = .{ .path = b.path("src/unit_tests.zig"), .mode = .simple },
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = mode,
|
.optimize = mode,
|
||||||
});
|
});
|
||||||
@@ -195,7 +195,7 @@ fn common(
|
|||||||
step.root_module.addImport("asyncio", asyncio);
|
step.root_module.addImport("asyncio", asyncio);
|
||||||
|
|
||||||
const tlsmod = b.addModule("tls", .{
|
const tlsmod = b.addModule("tls", .{
|
||||||
.root_source_file = b.path("vendor/tls.zig/src/main.zig"),
|
.root_source_file = b.path("vendor/tls.zig/src/root.zig"),
|
||||||
});
|
});
|
||||||
step.root_module.addImport("tls", tlsmod);
|
step.root_module.addImport("tls", tlsmod);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,16 +156,16 @@ pub const Session = struct {
|
|||||||
|
|
||||||
const ContextT = @TypeOf(ctx);
|
const ContextT = @TypeOf(ctx);
|
||||||
const InspectorContainer = switch (@typeInfo(ContextT)) {
|
const InspectorContainer = switch (@typeInfo(ContextT)) {
|
||||||
.Struct => ContextT,
|
.@"struct" => ContextT,
|
||||||
.Pointer => |ptr| ptr.child,
|
.pointer => |ptr| ptr.child,
|
||||||
.Void => NoopInspector,
|
.void => NoopInspector,
|
||||||
else => @compileError("invalid context type"),
|
else => @compileError("invalid context type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// const ctx_opaque = @as(*anyopaque, @ptrCast(ctx));
|
// const ctx_opaque = @as(*anyopaque, @ptrCast(ctx));
|
||||||
self.inspector = try jsruntime.Inspector.init(
|
self.inspector = try jsruntime.Inspector.init(
|
||||||
arena,
|
arena,
|
||||||
self.env, // TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
|
&self.env,
|
||||||
if (@TypeOf(ctx) == void) @constCast(@ptrCast(&{})) else ctx,
|
if (@TypeOf(ctx) == void) @constCast(@ptrCast(&{})) else ctx,
|
||||||
InspectorContainer.onInspectorResponse,
|
InspectorContainer.onInspectorResponse,
|
||||||
InspectorContainer.onInspectorEvent,
|
InspectorContainer.onInspectorEvent,
|
||||||
@@ -231,7 +231,7 @@ pub const Session = struct {
|
|||||||
|
|
||||||
// load polyfills
|
// load polyfills
|
||||||
// TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
|
// TODO: change to 'env' when https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
|
||||||
try polyfill.load(self.arena.allocator(), self.env);
|
try polyfill.load(self.arena.allocator(), &self.env);
|
||||||
|
|
||||||
// inspector
|
// inspector
|
||||||
self.contextCreated(page, aux_data);
|
self.contextCreated(page, aux_data);
|
||||||
@@ -264,7 +264,7 @@ pub const Session = struct {
|
|||||||
|
|
||||||
fn contextCreated(self: *Session, page: *Page, aux_data: ?[]const u8) void {
|
fn contextCreated(self: *Session, page: *Page, aux_data: ?[]const u8) void {
|
||||||
log.debug("inspector context created", .{});
|
log.debug("inspector context created", .{});
|
||||||
self.inspector.contextCreated(self.env, "", page.origin orelse "://", aux_data);
|
self.inspector.contextCreated(&self.env, "", page.origin orelse "://", aux_data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ pub const Page = struct {
|
|||||||
pub fn wait(self: *Page) !void {
|
pub fn wait(self: *Page) !void {
|
||||||
// try catch
|
// try catch
|
||||||
var try_catch: jsruntime.TryCatch = undefined;
|
var try_catch: jsruntime.TryCatch = undefined;
|
||||||
try_catch.init(self.session.env);
|
try_catch.init(&self.session.env);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
self.session.env.wait() catch |err| {
|
self.session.env.wait() catch |err| {
|
||||||
@@ -324,7 +324,7 @@ pub const Page = struct {
|
|||||||
if (err == error.EnvNotStarted) return;
|
if (err == error.EnvNotStarted) return;
|
||||||
|
|
||||||
const arena = self.arena;
|
const arena = self.arena;
|
||||||
if (try try_catch.err(arena, self.session.env)) |msg| {
|
if (try try_catch.err(arena, &self.session.env)) |msg| {
|
||||||
defer arena.free(msg);
|
defer arena.free(msg);
|
||||||
log.info("wait error: {s}", .{msg});
|
log.info("wait error: {s}", .{msg});
|
||||||
return;
|
return;
|
||||||
@@ -591,9 +591,7 @@ pub const Page = struct {
|
|||||||
// TODO handle charset attribute
|
// TODO handle charset attribute
|
||||||
const opt_text = try parser.nodeTextContent(parser.elementToNode(s.element));
|
const opt_text = try parser.nodeTextContent(parser.elementToNode(s.element));
|
||||||
if (opt_text) |text| {
|
if (opt_text) |text| {
|
||||||
// TODO: change to &self.session.env when
|
try s.eval(self.arena, &self.session.env, text);
|
||||||
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
|
|
||||||
try s.eval(self.arena, self.session.env, text);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,11 +654,8 @@ pub const Page = struct {
|
|||||||
// received.
|
// received.
|
||||||
fn fetchScript(self: *const Page, s: *const Script) !void {
|
fn fetchScript(self: *const Page, s: *const Script) !void {
|
||||||
const arena = self.arena;
|
const arena = self.arena;
|
||||||
|
|
||||||
const body = try self.fetchData(arena, s.src, null);
|
const body = try self.fetchData(arena, s.src, null);
|
||||||
// TODO: change to &self.session.env when
|
try s.eval(arena, &self.session.env, body);
|
||||||
// https://github.com/lightpanda-io/zig-js-runtime/pull/285 lands
|
|
||||||
try s.eval(arena, self.session.env, body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Script = struct {
|
const Script = struct {
|
||||||
@@ -683,9 +678,8 @@ pub const Page = struct {
|
|||||||
|
|
||||||
return .{
|
return .{
|
||||||
.element = e,
|
.element = e,
|
||||||
.kind = kind(try parser.elementGetAttribute(e, "type")),
|
.kind = parseKind(try parser.elementGetAttribute(e, "type")),
|
||||||
.is_async = try parser.elementGetAttribute(e, "async") != null,
|
.is_async = try parser.elementGetAttribute(e, "async") != null,
|
||||||
|
|
||||||
.src = try parser.elementGetAttribute(e, "src") orelse "inline",
|
.src = try parser.elementGetAttribute(e, "src") orelse "inline",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -695,7 +689,7 @@ pub const Page = struct {
|
|||||||
// > type indicates that the script is a "classic script", containing
|
// > type indicates that the script is a "classic script", containing
|
||||||
// > JavaScript code.
|
// > JavaScript code.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attribute_is_not_set_default_an_empty_string_or_a_javascript_mime_type
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attribute_is_not_set_default_an_empty_string_or_a_javascript_mime_type
|
||||||
fn kind(stype: ?[]const u8) Kind {
|
fn parseKind(stype: ?[]const u8) Kind {
|
||||||
if (stype == null or stype.?.len == 0) return .javascript;
|
if (stype == null or stype.?.len == 0) return .javascript;
|
||||||
if (std.mem.eql(u8, stype.?, "application/javascript")) return .javascript;
|
if (std.mem.eql(u8, stype.?, "application/javascript")) return .javascript;
|
||||||
if (std.mem.eql(u8, stype.?, "module")) return .module;
|
if (std.mem.eql(u8, stype.?, "module")) return .module;
|
||||||
@@ -703,7 +697,7 @@ pub const Page = struct {
|
|||||||
return .unknown;
|
return .unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(self: Script, arena: Allocator, env: Env, body: []const u8) !void {
|
fn eval(self: Script, arena: Allocator, env: *const Env, body: []const u8) !void {
|
||||||
var try_catch: jsruntime.TryCatch = undefined;
|
var try_catch: jsruntime.TryCatch = undefined;
|
||||||
try_catch.init(env);
|
try_catch.init(env);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ pub const Mime = struct {
|
|||||||
const bit_len = @bitSizeOf(@TypeOf(target.*)) - 8;
|
const bit_len = @bitSizeOf(@TypeOf(target.*)) - 8;
|
||||||
const byte_len = bit_len / 8;
|
const byte_len = bit_len / 8;
|
||||||
|
|
||||||
const T = @Type(.{ .Int = .{
|
const T = @Type(.{ .int = .{
|
||||||
.bits = bit_len,
|
.bits = bit_len,
|
||||||
.signedness = .unsigned,
|
.signedness = .unsigned,
|
||||||
} });
|
} });
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
pub fn sendResult(self: *Self, result: anytype, opts: SendResultOpts) !void {
|
pub fn sendResult(self: *Self, result: anytype, opts: SendResultOpts) !void {
|
||||||
return self.sender.sendJSON(.{
|
return self.sender.sendJSON(.{
|
||||||
.id = self.input.id,
|
.id = self.input.id,
|
||||||
.result = if (comptime @typeInfo(@TypeOf(result)) == .Null) struct {}{} else result,
|
.result = if (comptime @typeInfo(@TypeOf(result)) == .null) struct {}{} else result,
|
||||||
.sessionId = if (opts.include_session_id) self.input.session_id else null,
|
.sessionId = if (opts.include_session_id) self.input.session_id else null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -466,7 +466,7 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type {
|
|||||||
// Events ALWAYS go to the client. self.sender should not be used
|
// Events ALWAYS go to the client. self.sender should not be used
|
||||||
return self.cdp.sendJSON(.{
|
return self.cdp.sendJSON(.{
|
||||||
.method = method,
|
.method = method,
|
||||||
.params = if (comptime @typeInfo(@TypeOf(p)) == .Null) struct {}{} else p,
|
.params = if (comptime @typeInfo(@TypeOf(p)) == .null) struct {}{} else p,
|
||||||
.sessionId = opts.session_id,
|
.sessionId = opts.session_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,8 +174,8 @@ const TestContext = struct {
|
|||||||
|
|
||||||
pub fn processMessage(self: *TestContext, msg: anytype) !void {
|
pub fn processMessage(self: *TestContext, msg: anytype) !void {
|
||||||
var json_message: []const u8 = undefined;
|
var json_message: []const u8 = undefined;
|
||||||
if (@typeInfo(@TypeOf(msg)) != .Pointer) {
|
if (@typeInfo(@TypeOf(msg)) != .pointer) {
|
||||||
json_message = try json.stringifyAlloc(self.arena.allocator(), msg, .{});
|
json_message = try std.json.stringifyAlloc(self.arena.allocator(), msg, .{});
|
||||||
} else {
|
} else {
|
||||||
// assume this is a string we want to send as-is, if it isn't, we'll
|
// assume this is a string we want to send as-is, if it isn't, we'll
|
||||||
// get a compile error, so no big deal.
|
// get a compile error, so no big deal.
|
||||||
@@ -196,7 +196,7 @@ const TestContext = struct {
|
|||||||
pub fn expectSentResult(self: *TestContext, expected: anytype, opts: ExpectResultOpts) !void {
|
pub fn expectSentResult(self: *TestContext, expected: anytype, opts: ExpectResultOpts) !void {
|
||||||
const expected_result = .{
|
const expected_result = .{
|
||||||
.id = opts.id,
|
.id = opts.id,
|
||||||
.result = if (comptime @typeInfo(@TypeOf(expected)) == .Null) struct {}{} else expected,
|
.result = if (comptime @typeInfo(@TypeOf(expected)) == .null) struct {}{} else expected,
|
||||||
.sessionId = opts.session_id,
|
.sessionId = opts.session_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ const TestContext = struct {
|
|||||||
pub fn expectSentEvent(self: *TestContext, method: []const u8, params: anytype, opts: ExpectEventOpts) !void {
|
pub fn expectSentEvent(self: *TestContext, method: []const u8, params: anytype, opts: ExpectEventOpts) !void {
|
||||||
const expected_event = .{
|
const expected_event = .{
|
||||||
.method = method,
|
.method = method,
|
||||||
.params = if (comptime @typeInfo(@TypeOf(params)) == .Null) struct {}{} else params,
|
.params = if (comptime @typeInfo(@TypeOf(params)) == .null) struct {}{} else params,
|
||||||
.sessionId = opts.session_id,
|
.sessionId = opts.session_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -323,96 +323,3 @@ fn compareJsonValues(a: std.json.Value, b: std.json.Value) bool {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn compareAnyToJsonValue(expected: anytype, actual: json.Value) bool {
|
|
||||||
// switch (@typeInfo(@TypeOf(expected))) {
|
|
||||||
// .Optional => {
|
|
||||||
// if (expected) |e| {
|
|
||||||
// return compareAnyToJsonValue(e, actual);
|
|
||||||
// }
|
|
||||||
// return actual == .null;
|
|
||||||
// },
|
|
||||||
// .Int, .ComptimeInt => {
|
|
||||||
// if (actual != .integer) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return expected == actual.integer;
|
|
||||||
// },
|
|
||||||
// .Float, .ComptimeFloat => {
|
|
||||||
// if (actual != .float) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return expected == actual.float;
|
|
||||||
// },
|
|
||||||
// .Bool => {
|
|
||||||
// if (actual != .bool) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return expected == actual.bool;
|
|
||||||
// },
|
|
||||||
// .Pointer => |ptr| switch (ptr.size) {
|
|
||||||
// .One => switch (@typeInfo(ptr.child)) {
|
|
||||||
// .Struct => return compareAnyToJsonValue(expected.*, actual),
|
|
||||||
// .Array => |arr| if (arr.child == u8) {
|
|
||||||
// if (actual != .string) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return std.mem.eql(u8, expected, actual.string);
|
|
||||||
// },
|
|
||||||
// else => {},
|
|
||||||
// },
|
|
||||||
// .Slice => switch (ptr.child) {
|
|
||||||
// u8 => {
|
|
||||||
// if (actual != .string) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// return std.mem.eql(u8, expected, actual.string);
|
|
||||||
// },
|
|
||||||
// else => {},
|
|
||||||
// },
|
|
||||||
// else => {},
|
|
||||||
// },
|
|
||||||
// .Struct => |s| {
|
|
||||||
// if (s.is_tuple) {
|
|
||||||
// // how an array might look in an anytype
|
|
||||||
// if (actual != .array) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// if (s.fields.len != actual.array.items.len) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// inline for (s.fields, 0..) |f, i| {
|
|
||||||
// const e = @field(expected, f.name);
|
|
||||||
// if (compareAnyToJsonValue(e, actual.array.items[i]) == false) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (s.fields.len == 0) {
|
|
||||||
// return (actual == .array and actual.array.items.len == 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (actual != .object) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// inline for (s.fields) |f| {
|
|
||||||
// const e = @field(expected, f.name);
|
|
||||||
// if (actual.object.get(f.name)) |a| {
|
|
||||||
// if (compareAnyToJsonValue(e, a) == false) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// } else if (@typeInfo(f.type) != .Optional or e != null) {
|
|
||||||
// // We don't JSON serialize nulls. So if we're expecting
|
|
||||||
// // a null, that should show up as a missing field.
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// },
|
|
||||||
// else => {},
|
|
||||||
// }
|
|
||||||
// @compileError("Can't compare " ++ @typeName(@TypeOf(expected)));
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ pub fn Union(interfaces: anytype) type {
|
|||||||
.decls = &.{},
|
.decls = &.{},
|
||||||
.is_exhaustive = true,
|
.is_exhaustive = true,
|
||||||
};
|
};
|
||||||
const enum_T = @Type(.{ .Enum = enum_info });
|
const enum_T = @Type(.{ .@"enum" = enum_info });
|
||||||
|
|
||||||
// third iteration to generate union type
|
// third iteration to generate union type
|
||||||
var union_fields: [fields.len]Type.UnionField = undefined;
|
var union_fields: [fields.len]Type.UnionField = undefined;
|
||||||
@@ -79,7 +79,7 @@ pub fn Union(interfaces: anytype) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return @Type(.{ .Union = .{
|
return @Type(.{ .@"union" = .{
|
||||||
.layout = .auto,
|
.layout = .auto,
|
||||||
.tag_type = enum_T,
|
.tag_type = enum_T,
|
||||||
.fields = &union_fields,
|
.fields = &union_fields,
|
||||||
@@ -115,12 +115,12 @@ pub fn Tuple(args: anytype) type {
|
|||||||
// has to be true in order to properly capture the default value
|
// has to be true in order to properly capture the default value
|
||||||
.is_comptime = true,
|
.is_comptime = true,
|
||||||
.alignment = @alignOf(type),
|
.alignment = @alignOf(type),
|
||||||
.default_value = @ptrCast(&interfaces[i]),
|
.default_value_ptr = @ptrCast(&interfaces[i]),
|
||||||
};
|
};
|
||||||
field_index += 1;
|
field_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return @Type(.{ .Struct = .{
|
return @Type(.{ .@"struct" = .{
|
||||||
.layout = .auto,
|
.layout = .auto,
|
||||||
.fields = &fields,
|
.fields = &fields,
|
||||||
.decls = &.{},
|
.decls = &.{},
|
||||||
@@ -130,7 +130,7 @@ pub fn Tuple(args: anytype) type {
|
|||||||
|
|
||||||
fn countInterfaces(args: anytype, count: usize) usize {
|
fn countInterfaces(args: anytype, count: usize) usize {
|
||||||
var new_count = count;
|
var new_count = count;
|
||||||
for (@typeInfo(@TypeOf(args)).Struct.fields) |f| {
|
for (@typeInfo(@TypeOf(args)).@"struct".fields) |f| {
|
||||||
const member = @field(args, f.name);
|
const member = @field(args, f.name);
|
||||||
if (@TypeOf(member) == type) {
|
if (@TypeOf(member) == type) {
|
||||||
new_count += 1;
|
new_count += 1;
|
||||||
@@ -143,7 +143,7 @@ fn countInterfaces(args: anytype, count: usize) usize {
|
|||||||
|
|
||||||
fn flattenInterfaces(args: anytype, interfaces: []type, index: usize) usize {
|
fn flattenInterfaces(args: anytype, interfaces: []type, index: usize) usize {
|
||||||
var new_index = index;
|
var new_index = index;
|
||||||
for (@typeInfo(@TypeOf(args)).Struct.fields) |f| {
|
for (@typeInfo(@TypeOf(args)).@"struct".fields) |f| {
|
||||||
const member = @field(args, f.name);
|
const member = @field(args, f.name);
|
||||||
if (@TypeOf(member) == type) {
|
if (@TypeOf(member) == type) {
|
||||||
interfaces[new_index] = member;
|
interfaces[new_index] = member;
|
||||||
@@ -186,7 +186,7 @@ test "generate.Union" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
|
const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
|
||||||
const ti = @typeInfo(value).Union;
|
const ti = @typeInfo(value).@"union";
|
||||||
try std.testing.expectEqual(3, ti.fields.len);
|
try std.testing.expectEqual(3, ti.fields.len);
|
||||||
try std.testing.expectEqualStrings("*generate.test.generate.Union.Astruct.Other", @typeName(ti.fields[0].type));
|
try std.testing.expectEqualStrings("*generate.test.generate.Union.Astruct.Other", @typeName(ti.fields[0].type));
|
||||||
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
|
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
|
||||||
@@ -209,7 +209,7 @@ test "generate.Tuple" {
|
|||||||
|
|
||||||
{
|
{
|
||||||
const tuple = Tuple(.{ Astruct, Bstruct }){};
|
const tuple = Tuple(.{ Astruct, Bstruct }){};
|
||||||
const ti = @typeInfo(@TypeOf(tuple)).Struct;
|
const ti = @typeInfo(@TypeOf(tuple)).@"struct";
|
||||||
try std.testing.expectEqual(true, ti.is_tuple);
|
try std.testing.expectEqual(true, ti.is_tuple);
|
||||||
try std.testing.expectEqual(2, ti.fields.len);
|
try std.testing.expectEqual(2, ti.fields.len);
|
||||||
try std.testing.expectEqual(Astruct, tuple.@"0");
|
try std.testing.expectEqual(Astruct, tuple.@"0");
|
||||||
@@ -219,7 +219,7 @@ test "generate.Tuple" {
|
|||||||
{
|
{
|
||||||
// dedupe
|
// dedupe
|
||||||
const tuple = Tuple(.{ Cstruct, Astruct, .{Astruct}, Bstruct, .{ Astruct, .{ Astruct, Bstruct } } }){};
|
const tuple = Tuple(.{ Cstruct, Astruct, .{Astruct}, Bstruct, .{ Astruct, .{ Astruct, Bstruct } } }){};
|
||||||
const ti = @typeInfo(@TypeOf(tuple)).Struct;
|
const ti = @typeInfo(@TypeOf(tuple)).@"struct";
|
||||||
try std.testing.expectEqual(true, ti.is_tuple);
|
try std.testing.expectEqual(true, ti.is_tuple);
|
||||||
try std.testing.expectEqual(3, ti.fields.len);
|
try std.testing.expectEqual(3, ti.fields.len);
|
||||||
try std.testing.expectEqual(Cstruct, tuple.@"0");
|
try std.testing.expectEqual(Cstruct, tuple.@"0");
|
||||||
|
|||||||
@@ -1358,7 +1358,7 @@ pub fn connectTcp(client: *Client, host: []const u8, port: u16, protocol: Connec
|
|||||||
|
|
||||||
conn.data.tls_client.* = tls23.client(stream, .{
|
conn.data.tls_client.* = tls23.client(stream, .{
|
||||||
.host = host,
|
.host = host,
|
||||||
.root_ca = client.ca_bundle,
|
.root_ca = .{ .bundle = client.ca_bundle },
|
||||||
}) catch return error.TlsInitializationFailed;
|
}) catch return error.TlsInitializationFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub fn Incrementing(comptime T: type, comptime prefix: []const u8) type {
|
|||||||
break :blk b;
|
break :blk b;
|
||||||
};
|
};
|
||||||
|
|
||||||
const PrefixIntType = @Type(.{ .Int = .{
|
const PrefixIntType = @Type(.{ .int = .{
|
||||||
.bits = NUMERIC_START * 8,
|
.bits = NUMERIC_START * 8,
|
||||||
.signedness = .unsigned,
|
.signedness = .unsigned,
|
||||||
} });
|
} });
|
||||||
|
|||||||
22
src/log.zig
22
src/log.zig
@@ -151,7 +151,7 @@ fn LogT(comptime Out: type, comptime enhanced_readability: bool) type {
|
|||||||
buffer.appendSliceAssumeCapacity(inject);
|
buffer.appendSliceAssumeCapacity(inject);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline for (@typeInfo(@TypeOf(data)).Struct.fields) |f| {
|
inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |f| {
|
||||||
// + 2 for the leading space and the equal sign
|
// + 2 for the leading space and the equal sign
|
||||||
// + 5 to save space for null/false/true common values
|
// + 5 to save space for null/false/true common values
|
||||||
const key_len = f.name.len + 7;
|
const key_len = f.name.len + 7;
|
||||||
@@ -179,30 +179,30 @@ fn LogT(comptime Out: type, comptime enhanced_readability: bool) type {
|
|||||||
fn writeValue(allocator: Allocator, buffer: *std.ArrayListUnmanaged(u8), value: anytype) !void {
|
fn writeValue(allocator: Allocator, buffer: *std.ArrayListUnmanaged(u8), value: anytype) !void {
|
||||||
const T = @TypeOf(value);
|
const T = @TypeOf(value);
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
.Optional => {
|
.optional => {
|
||||||
if (value) |v| {
|
if (value) |v| {
|
||||||
return writeValue(allocator, buffer, v);
|
return writeValue(allocator, buffer, v);
|
||||||
}
|
}
|
||||||
// in _log, we reserved space for a value of up to 5 bytes.
|
// in _log, we reserved space for a value of up to 5 bytes.
|
||||||
return buffer.appendSliceAssumeCapacity("null");
|
return buffer.appendSliceAssumeCapacity("null");
|
||||||
},
|
},
|
||||||
.ComptimeInt, .Int, .ComptimeFloat, .Float => {
|
.comptime_int, .int, .comptime_float, .float => {
|
||||||
return std.fmt.format(buffer.writer(allocator), "{d}", .{value});
|
return std.fmt.format(buffer.writer(allocator), "{d}", .{value});
|
||||||
},
|
},
|
||||||
.Bool => {
|
.bool => {
|
||||||
// in _log, we reserved space for a value of up to 5 bytes.
|
// in _log, we reserved space for a value of up to 5 bytes.
|
||||||
return buffer.appendSliceAssumeCapacity(if (value) "true" else "false");
|
return buffer.appendSliceAssumeCapacity(if (value) "true" else "false");
|
||||||
},
|
},
|
||||||
.ErrorSet => return buffer.appendSlice(allocator, @errorName(value)),
|
.error_set => return buffer.appendSlice(allocator, @errorName(value)),
|
||||||
.Enum => return buffer.appendSlice(allocator, @tagName(value)),
|
.@"enum" => return buffer.appendSlice(allocator, @tagName(value)),
|
||||||
.Array => return writeValue(allocator, buffer, &value),
|
.array => return writeValue(allocator, buffer, &value),
|
||||||
.Pointer => |ptr| switch (ptr.size) {
|
.pointer => |ptr| switch (ptr.size) {
|
||||||
.Slice => switch (ptr.child) {
|
.slice => switch (ptr.child) {
|
||||||
u8 => return writeString(allocator, buffer, value),
|
u8 => return writeString(allocator, buffer, value),
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
.One => switch (@typeInfo(ptr.child)) {
|
.one => switch (@typeInfo(ptr.child)) {
|
||||||
.Array => |arr| if (arr.child == u8) {
|
.array => |arr| if (arr.child == u8) {
|
||||||
return writeString(allocator, buffer, value);
|
return writeString(allocator, buffer, value);
|
||||||
},
|
},
|
||||||
else => return false,
|
else => return false,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const version = @import("build_info").git_commit;
|
|||||||
|
|
||||||
const log = std.log.scoped(.cli);
|
const log = std.log.scoped(.cli);
|
||||||
|
|
||||||
pub const std_options = .{
|
pub const std_options = std.Options{
|
||||||
// Set the log level to info
|
// Set the log level to info
|
||||||
.log_level = .debug,
|
.log_level = .debug,
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ fn parseFetchArgs(
|
|||||||
var verbose: bool = builtin.mode == .Debug; // In debug mode, force verbose.
|
var verbose: bool = builtin.mode == .Debug; // In debug mode, force verbose.
|
||||||
fn logFn(
|
fn logFn(
|
||||||
comptime level: std.log.Level,
|
comptime level: std.log.Level,
|
||||||
comptime scope: @Type(.EnumLiteral),
|
comptime scope: @Type(.enum_literal),
|
||||||
comptime format: []const u8,
|
comptime format: []const u8,
|
||||||
args: anytype,
|
args: anytype,
|
||||||
) void {
|
) void {
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ pub const Tag = enum(u8) {
|
|||||||
|
|
||||||
pub fn all() []Tag {
|
pub fn all() []Tag {
|
||||||
comptime {
|
comptime {
|
||||||
const info = @typeInfo(Tag).Enum;
|
const info = @typeInfo(Tag).@"enum";
|
||||||
var l: [info.fields.len]Tag = undefined;
|
var l: [info.fields.len]Tag = undefined;
|
||||||
for (info.fields, 0..) |field, i| {
|
for (info.fields, 0..) |field, i| {
|
||||||
l[i] = @as(Tag, @enumFromInt(field.value));
|
l[i] = @as(Tag, @enumFromInt(field.value));
|
||||||
@@ -804,7 +804,7 @@ pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
|
|||||||
pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 {
|
pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 {
|
||||||
std.debug.assert(@inComptime());
|
std.debug.assert(@inComptime());
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
.Struct => |ti| {
|
.@"struct" => |ti| {
|
||||||
for (ti.fields) |f| {
|
for (ti.fields) |f| {
|
||||||
if (f.type == EventTargetTBase) return f.name;
|
if (f.type == EventTargetTBase) return f.name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ pub fn testExecFn(
|
|||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
js_env: *jsruntime.Env,
|
js_env: *jsruntime.Env,
|
||||||
) anyerror!void {
|
) anyerror!void {
|
||||||
try @import("polyfill.zig").load(alloc, js_env.*);
|
try @import("polyfill.zig").load(alloc, js_env);
|
||||||
|
|
||||||
var fetch = [_]Case{
|
var fetch = [_]Case{
|
||||||
.{
|
.{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const modules = [_]struct {
|
|||||||
.{ .name = "polyfill-fetch", .source = @import("fetch.zig").source },
|
.{ .name = "polyfill-fetch", .source = @import("fetch.zig").source },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn load(alloc: std.mem.Allocator, env: Env) !void {
|
pub fn load(alloc: std.mem.Allocator, env: *const Env) !void {
|
||||||
var try_catch: jsruntime.TryCatch = undefined;
|
var try_catch: jsruntime.TryCatch = undefined;
|
||||||
try_catch.init(env);
|
try_catch.init(env);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|||||||
@@ -57,13 +57,6 @@ const Server = struct {
|
|||||||
listener: posix.socket_t,
|
listener: posix.socket_t,
|
||||||
timeout: u64,
|
timeout: u64,
|
||||||
|
|
||||||
// A memory poor for our Clients. Because we only allow 1 client to be
|
|
||||||
// connected at a time, and because of the way we accept, we don't need
|
|
||||||
// a lock for this, since the creation of a new client cannot happen at the
|
|
||||||
// same time as the destruction of a client.
|
|
||||||
client_pool: std.heap.MemoryPool(Client),
|
|
||||||
client_pool_lock: std.Thread.Mutex = .{},
|
|
||||||
|
|
||||||
// I/O fields
|
// I/O fields
|
||||||
accept_completion: Completion,
|
accept_completion: Completion,
|
||||||
|
|
||||||
@@ -71,7 +64,7 @@ const Server = struct {
|
|||||||
json_version_response: []const u8,
|
json_version_response: []const u8,
|
||||||
|
|
||||||
fn deinit(self: *Server) void {
|
fn deinit(self: *Server) void {
|
||||||
self.client_pool.deinit();
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queueAccept(self: *Server) void {
|
fn queueAccept(self: *Server) void {
|
||||||
@@ -102,28 +95,14 @@ const Server = struct {
|
|||||||
result: AcceptError!posix.socket_t,
|
result: AcceptError!posix.socket_t,
|
||||||
) !void {
|
) !void {
|
||||||
const socket = try result;
|
const socket = try result;
|
||||||
|
const client = try self.allocator.create(Client);
|
||||||
const client = blk: {
|
|
||||||
self.client_pool_lock.lock();
|
|
||||||
defer self.client_pool_lock.unlock();
|
|
||||||
break :blk try self.client_pool.create();
|
|
||||||
};
|
|
||||||
|
|
||||||
errdefer {
|
|
||||||
self.client_pool_lock.lock();
|
|
||||||
self.client_pool.destroy(client);
|
|
||||||
self.client_pool_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
client.* = Client.init(socket, self);
|
client.* = Client.init(socket, self);
|
||||||
client.start();
|
client.start();
|
||||||
log.info("client connected", .{});
|
log.info("client connected", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn releaseClient(self: *Server, client: *Client) void {
|
fn releaseClient(self: *Server, client: *Client) void {
|
||||||
self.client_pool_lock.lock();
|
self.allocator.destroy(client);
|
||||||
self.client_pool.destroy(client);
|
|
||||||
self.client_pool_lock.unlock();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1053,7 +1032,6 @@ pub fn run(
|
|||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.accept_completion = undefined,
|
.accept_completion = undefined,
|
||||||
.json_version_response = json_version_response,
|
.json_version_response = json_version_response,
|
||||||
.client_pool = std.heap.MemoryPool(Client).init(allocator),
|
|
||||||
};
|
};
|
||||||
defer server.deinit();
|
defer server.deinit();
|
||||||
|
|
||||||
@@ -1488,8 +1466,8 @@ fn createTestClient() !TestClient {
|
|||||||
const stream = try std.net.tcpConnectToAddress(address);
|
const stream = try std.net.tcpConnectToAddress(address);
|
||||||
|
|
||||||
const timeout = std.mem.toBytes(posix.timeval{
|
const timeout = std.mem.toBytes(posix.timeval{
|
||||||
.tv_sec = 2,
|
.sec = 2,
|
||||||
.tv_usec = 0,
|
.usec = 0,
|
||||||
});
|
});
|
||||||
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout);
|
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.RCVTIMEO, &timeout);
|
||||||
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout);
|
try posix.setsockopt(stream.handle, posix.SOL.SOCKET, posix.SO.SNDTIMEO, &timeout);
|
||||||
|
|||||||
@@ -922,7 +922,7 @@ fn expectAttribute(expected: anytype, url: ?[]const u8, set_cookie: []const u8)
|
|||||||
var cookie = try Cookie.parse(testing.allocator, uri, set_cookie);
|
var cookie = try Cookie.parse(testing.allocator, uri, set_cookie);
|
||||||
defer cookie.deinit();
|
defer cookie.deinit();
|
||||||
|
|
||||||
inline for (@typeInfo(@TypeOf(expected)).Struct.fields) |f| {
|
inline for (@typeInfo(@TypeOf(expected)).@"struct".fields) |f| {
|
||||||
if (comptime std.mem.eql(u8, f.name, "expires")) {
|
if (comptime std.mem.eql(u8, f.name, "expires")) {
|
||||||
try testing.expectDelta(expected.expires, cookie.expires, 1);
|
try testing.expectDelta(expected.expires, cookie.expires, 1);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ pub fn asUint(comptime string: anytype) AsUintReturn(string) {
|
|||||||
|
|
||||||
fn AsUintReturn(comptime string: anytype) type {
|
fn AsUintReturn(comptime string: anytype) type {
|
||||||
return @Type(.{
|
return @Type(.{
|
||||||
.Int = .{
|
.int = .{
|
||||||
.bits = @bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0
|
.bits = @bitSizeOf(@TypeOf(string.*)) - 8, // (- 8) to exclude sentinel 0
|
||||||
.signedness = .unsigned,
|
.signedness = .unsigned,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ const App = @import("app.zig").App;
|
|||||||
// exactly how to assert equality
|
// exactly how to assert equality
|
||||||
pub fn expectEqual(expected: anytype, actual: anytype) !void {
|
pub fn expectEqual(expected: anytype, actual: anytype) !void {
|
||||||
switch (@typeInfo(@TypeOf(actual))) {
|
switch (@typeInfo(@TypeOf(actual))) {
|
||||||
.Array => |arr| if (arr.child == u8) {
|
.array => |arr| if (arr.child == u8) {
|
||||||
return std.testing.expectEqualStrings(expected, &actual);
|
return std.testing.expectEqualStrings(expected, &actual);
|
||||||
},
|
},
|
||||||
.Pointer => |ptr| {
|
.pointer => |ptr| {
|
||||||
if (ptr.child == u8) {
|
if (ptr.child == u8) {
|
||||||
return std.testing.expectEqualStrings(expected, actual);
|
return std.testing.expectEqualStrings(expected, actual);
|
||||||
} else if (comptime isStringArray(ptr.child)) {
|
} else if (comptime isStringArray(ptr.child)) {
|
||||||
@@ -23,19 +23,19 @@ pub fn expectEqual(expected: anytype, actual: anytype) !void {
|
|||||||
return expectString(expected, actual);
|
return expectString(expected, actual);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Struct => |structType| {
|
.@"struct" => |structType| {
|
||||||
inline for (structType.fields) |field| {
|
inline for (structType.fields) |field| {
|
||||||
try expectEqual(@field(expected, field.name), @field(actual, field.name));
|
try expectEqual(@field(expected, field.name), @field(actual, field.name));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
.Optional => {
|
.optional => {
|
||||||
if (actual == null) {
|
if (actual == null) {
|
||||||
return std.testing.expectEqual(null, expected);
|
return std.testing.expectEqual(null, expected);
|
||||||
}
|
}
|
||||||
return expectEqual(expected, actual.?);
|
return expectEqual(expected, actual.?);
|
||||||
},
|
},
|
||||||
.Union => |union_info| {
|
.@"union" => |union_info| {
|
||||||
if (union_info.tag_type == null) {
|
if (union_info.tag_type == null) {
|
||||||
@compileError("Unable to compare untagged union values");
|
@compileError("Unable to compare untagged union values");
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,12 @@ pub fn expectEqual(expected: anytype, actual: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
|
pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
|
||||||
if (@typeInfo(@TypeOf(expected)) == .Null) {
|
if (@typeInfo(@TypeOf(expected)) == .null) {
|
||||||
return std.testing.expectEqual(null, actual);
|
return std.testing.expectEqual(null, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (@typeInfo(@TypeOf(actual))) {
|
switch (@typeInfo(@TypeOf(actual))) {
|
||||||
.Optional => {
|
.optional => {
|
||||||
if (actual) |value| {
|
if (actual) |value| {
|
||||||
return expectDelta(expected, value, delta);
|
return expectDelta(expected, value, delta);
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (@typeInfo(@TypeOf(expected))) {
|
switch (@typeInfo(@TypeOf(expected))) {
|
||||||
.Optional => {
|
.optional => {
|
||||||
if (expected) |value| {
|
if (expected) |value| {
|
||||||
return expectDelta(value, actual, delta);
|
return expectDelta(value, actual, delta);
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ pub fn expectDelta(expected: anytype, actual: anytype, delta: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn isStringArray(comptime T: type) bool {
|
fn isStringArray(comptime T: type) bool {
|
||||||
if (!is(.Array)(T) and !isPtrTo(.Array)(T)) {
|
if (!is(.array)(T) and !isPtrTo(.array)(T)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return std.meta.Elem(T) == u8;
|
return std.meta.Elem(T) == u8;
|
||||||
@@ -124,7 +124,7 @@ pub fn isPtrTo(comptime id: std.builtin.TypeId) TraitFn {
|
|||||||
|
|
||||||
pub fn isSingleItemPtr(comptime T: type) bool {
|
pub fn isSingleItemPtr(comptime T: type) bool {
|
||||||
if (comptime is(.pointer)(T)) {
|
if (comptime is(.pointer)(T)) {
|
||||||
return @typeInfo(T).Pointer.size == .one;
|
return @typeInfo(T).pointer.size == .one;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ fn testParseQuery(expected: anytype, query: []const u8) !void {
|
|||||||
defer values.deinit();
|
defer values.deinit();
|
||||||
|
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
inline for (@typeInfo(@TypeOf(expected)).Struct.fields) |f| {
|
inline for (@typeInfo(@TypeOf(expected)).@"struct".fields) |f| {
|
||||||
const actual = values.get(f.name);
|
const actual = values.get(f.name);
|
||||||
const expect = @field(expected, f.name);
|
const expect = @field(expected, f.name);
|
||||||
try testing.expectEqual(expect.len, actual.len);
|
try testing.expectEqual(expect.len, actual.len);
|
||||||
|
|||||||
2
vendor/tls.zig
vendored
2
vendor/tls.zig
vendored
Submodule vendor/tls.zig updated: 0ea9e6d769...7eb35dabf8
2
vendor/zig-async-io
vendored
2
vendor/zig-async-io
vendored
Submodule vendor/zig-async-io updated: 073546a975...cc38625c82
2
vendor/zig-js-runtime
vendored
2
vendor/zig-js-runtime
vendored
Submodule vendor/zig-js-runtime updated: 9122de43e4...edeb92988d
Reference in New Issue
Block a user