diff options
| author | Adam Goertz <adambgoertz@gmail.com> | 2023-07-12 02:45:51 +0000 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-29 00:32:43 -0700 |
| commit | b3cad98534a4a4406d848f7cbd28165ca005bc8a (patch) | |
| tree | a73855683e8bb98be5cc7e85270e383632d42f0e /lib/std | |
| parent | ed19ebc3605ec7e50166adf45f162dcf5540c42e (diff) | |
| download | zig-b3cad98534a4a4406d848f7cbd28165ca005bc8a.tar.gz zig-b3cad98534a4a4406d848f7cbd28165ca005bc8a.zip | |
Support file:/// URIs and relative paths
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/Uri.zig | 45 | ||||
| -rw-r--r-- | lib/std/os/windows.zig | 1 | ||||
| -rw-r--r-- | lib/std/os/windows/shlwapi.zig | 13 |
3 files changed, 54 insertions, 5 deletions
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index b27a3d7012..e2c23e5a1d 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -134,6 +134,7 @@ pub const ParseError = error{ UnexpectedCharacter, InvalidFormat, InvalidPort }; /// original `text`. Each component that is provided, will be non-`null`. pub fn parseWithoutScheme(text: []const u8) ParseError!Uri { var reader = SliceReader{ .slice = text }; + var uri = Uri{ .scheme = "", .user = null, @@ -145,13 +146,14 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri { .fragment = null, }; - if (reader.peekPrefix("//")) { // authority part + if (reader.peekPrefix("//")) a: { // authority part std.debug.assert(reader.get().? == '/'); std.debug.assert(reader.get().? == '/'); - const authority = reader.readUntil(isAuthoritySeparator); - if (authority.len == 0) - return error.InvalidFormat; + var authority = reader.readUntil(isAuthoritySeparator); + if (authority.len == 0) { + if (reader.peekPrefix("/")) break :a else return error.InvalidFormat; + } var start_of_host: usize = 0; if (std.mem.indexOf(u8, authority, "@")) |index| { @@ -224,7 +226,6 @@ pub fn format( try writer.writeAll(":"); if (uri.host) |host| { try writer.writeAll("//"); - if (uri.user) |user| { try writer.writeAll(user); if (uri.password) |password| { @@ -486,6 +487,23 @@ test "should fail gracefully" { try std.testing.expectEqual(@as(ParseError!Uri, error.InvalidFormat), parse("foobar://")); } +test "file" { + const parsed = try parse("file:///"); + try std.testing.expectEqualSlices(u8, "file", parsed.scheme); + try std.testing.expectEqual(@as(?[]const u8, null), parsed.host); + try std.testing.expectEqualSlices(u8, "/", parsed.path); + + const parsed2 = try parse("file:///an/absolute/path/to/something"); + try std.testing.expectEqualSlices(u8, "file", parsed2.scheme); + try std.testing.expectEqual(@as(?[]const u8, null), parsed2.host); + try std.testing.expectEqualSlices(u8, "/an/absolute/path/to/something", parsed2.path); + + const parsed3 = try parse("file://localhost/an/absolute/path/to/another/thing/"); + try std.testing.expectEqualSlices(u8, "file", parsed3.scheme); + try std.testing.expectEqualSlices(u8, "localhost", parsed3.host.?); + try std.testing.expectEqualSlices(u8, "/an/absolute/path/to/another/thing/", parsed3.path); +} + test "scheme" { try std.testing.expectEqualSlices(u8, "http", (try parse("http:_")).scheme); try std.testing.expectEqualSlices(u8, "scheme-mee", (try parse("scheme-mee:_")).scheme); @@ -695,3 +713,20 @@ test "URI query escaping" { defer std.testing.allocator.free(formatted_uri); try std.testing.expectEqualStrings("/?response-content-type=application%2Foctet-stream", formatted_uri); } + +test "format" { + const uri = Uri{ + .scheme = "file", + .user = null, + .password = null, + .host = null, + .port = null, + .path = "/foo/bar/baz", + .query = null, + .fragment = null, + }; + var buf = std.ArrayList(u8).init(std.testing.allocator); + defer buf.deinit(); + try uri.format("+/", .{}, buf.writer()); + try std.testing.expectEqualSlices(u8, "file:/foo/bar/baz", buf.items); +} diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index d40fee8db2..3522f238ec 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -30,6 +30,7 @@ pub const gdi32 = @import("windows/gdi32.zig"); pub const winmm = @import("windows/winmm.zig"); pub const crypt32 = @import("windows/crypt32.zig"); pub const nls = @import("windows/nls.zig"); +pub const shlwapi = @import("windows/shlwapi.zig"); pub const self_process_handle = @as(HANDLE, @ptrFromInt(maxInt(usize))); diff --git a/lib/std/os/windows/shlwapi.zig b/lib/std/os/windows/shlwapi.zig new file mode 100644 index 0000000000..0f0ceed576 --- /dev/null +++ b/lib/std/os/windows/shlwapi.zig @@ -0,0 +1,13 @@ +const std = @import("../../std.zig"); +const windows = std.os.windows; + +const DWORD = windows.DWORD; +const WINAPI = windows.WINAPI; +const HRESULT = windows.HRESULT; +const LPCSTR = windows.LPCSTR; +const LPSTR = windows.LPSTR; +const LPWSTR = windows.LPWSTR; +const LPCWSTR = windows.LPCWSTR; + +pub extern "shlwapi" fn PathCreateFromUrlW(pszUrl: LPCWSTR, pszPath: LPWSTR, pcchPath: *DWORD, dwFlags: DWORD) callconv(WINAPI) HRESULT; +pub extern "shlwapi" fn PathCreateFromUrlA(pszUrl: LPCSTR, pszPath: LPSTR, pcchPath: *DWORD, dwFlags: DWORD) callconv(WINAPI) HRESULT; |
