authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-24 14:01:09 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-24 14:01:09 -08:00
loge2aee9791d52d234b4b4196057508c8734038a7f
tree07bb8cbffb26eb463855fe6bc4179585e38baad4
parent20a830b847b756cea94e66812a39bfaf497cd2fc

populate href field


3 files changed, 31 insertions(+), 6 deletions(-)

generate.ts+1-1
......@@ -57,7 +57,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:
5757 try expect(u.pathname).toEqualString(pathname);
5858 try expect(u.search).toEqualString(search);
5959 try expect(u.hash).toEqualString(hash);
60 _ = href;
60 try expect(u.href).toEqualString(href);
6161}
6262
6363pub fn parseIDNAFail(comptime input: []const u8) !void {
url.zig+29-4
......@@ -11,7 +11,7 @@ pub const URL = struct {
1111 username: []const u8,
1212 password: []const u8,
1313 hostname: []const u8,
14 hostname_kind: HostKind = .name,
14 hostname_kind: HostKind,
1515 port: []const u8,
1616 host: []const u8,
1717 pathname: []const u8,
......@@ -19,12 +19,14 @@ pub const URL = struct {
1919 hash: []const u8,
2020
2121 pub const HostKind = enum {
22 unset,
2223 name,
2324 ipv4,
2425 ipv6,
2526 };
2627
2728 const Host = union(HostKind) {
29 unset: void,
2830 name: []const u8,
2931 ipv4: u32,
3032 ipv6: u128,
......@@ -87,7 +89,8 @@ pub const URL = struct {
8789
8890 var href = ManyArrayList(8 + 7, u8).init(alloc);
8991 defer href.deinit();
90 var hostname_kind: HostKind = .name;
92 var hostname_kind: HostKind = .unset;
93 var has_opaque_path = false;
9194 // scheme
9295 // :
9396 // //
......@@ -178,6 +181,7 @@ pub const URL = struct {
178181 else {
179182 href.clear(10);
180183 state = .opaque_path;
184 has_opaque_path = true;
181185 }
182186 }
183187 // 3. Otherwise, if state override is not given, set buffer to the empty string, state to no scheme state, and start over (from the first code point in input).
......@@ -402,7 +406,6 @@ pub const URL = struct {
402406 hostname_kind = h;
403407 buffer.clearRetainingCapacity();
404408 state = .port;
405 try href.set(8, ":");
406409 }
407410 // 3. Otherwise, if one of the following is true:
408411 // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
......@@ -479,6 +482,7 @@ pub const URL = struct {
479482 try href.set(0, "file");
480483 // 2. Set url’s host to the empty string.
481484 href.clear(7);
485 hostname_kind = .name;
482486 // 3. If c is U+002F (/) or U+005C (\), then:
483487 if (c == '/' or c == '\\') {
484488 // 1. If c is U+005C (\), invalid-reverse-solidus validation error.
......@@ -574,6 +578,7 @@ pub const URL = struct {
574578 else if (buffer.items.len == 0) {
575579 // 1. Set url’s host to the empty string.
576580 href.clear(7);
581 hostname_kind = .name;
577582 // 2. If state override is given, then return.
578583 if (state_override != null) break;
579584 // 3. Set state to path start state.
......@@ -814,6 +819,25 @@ pub const URL = struct {
814819 }
815820 }
816821
822 if (hostname_kind != .unset) {
823 try href.appendSlice(2, "//");
824 }
825 if (href.lengths[5] > 0) {
826 try href.set(4, ":");
827 }
828 if (href.lengths[3] > 0 or href.lengths[5] > 0) {
829 try href.set(6, "@");
830 }
831 if (href.lengths[9] > 0) {
832 try href.set(8, ":");
833 }
834
835 var path_offset: usize = 0;
836 if (hostname_kind == .unset and !has_opaque_path and std.mem.startsWith(u8, href.items(10), "//")) {
837 try href.replace(10, 0, 0, "/.");
838 path_offset += 2;
839 }
840
817841 const _href = try href.list.toOwnedSlice();
818842
819843 const url: URL = .{
......@@ -825,7 +849,7 @@ pub const URL = struct {
825849 .hostname_kind = hostname_kind,
826850 .port = _href[extras.sum(usize, href.lengths[0..9])..][0..href.lengths[9]],
827851 .host = _href[extras.sum(usize, href.lengths[0..7])..][0..extras.sum(usize, href.lengths[7..][0..if (href.lengths[9] == 0) 1 else 3])],
828 .pathname = _href[extras.sum(usize, href.lengths[0..10])..][0..href.lengths[10]],
852 .pathname = _href[extras.sum(usize, href.lengths[0..10])..][0..href.lengths[10]][path_offset..],
829853 .search = if (href.lengths[12] == 0) "" else _href[extras.sum(usize, href.lengths[0..11])..][0..extras.sum(usize, href.lengths[11..][0..2])],
830854 .hash = if (href.lengths[14] == 0) "" else _href[extras.sum(usize, href.lengths[0..13])..][0..extras.sum(usize, href.lengths[13..][0..2])],
831855 };
......@@ -1466,6 +1490,7 @@ fn percentEncodeML(list: *ManyArrayList(15, u8), n: usize, input: []const u8, co
14661490}
14671491fn setHost(href: *ManyArrayList(15, u8), h: URL.Host) !void {
14681492 switch (h) {
1493 .unset => unreachable,
14691494 .name => {
14701495 try href.set(7, h.name);
14711496 },
zig-out/test.zig+1-1
......@@ -27,7 +27,7 @@ pub fn parsePass(input: []const u8, base: ?[]const u8, href: []const u8, origin:
2727 try expect(u.pathname).toEqualString(pathname);
2828 try expect(u.search).toEqualString(search);
2929 try expect(u.hash).toEqualString(hash);
30 _ = href;
30 try expect(u.href).toEqualString(href);
3131}
3232
3333pub fn parseIDNAFail(comptime input: []const u8) !void {