diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-06-27 20:05:22 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-07-07 22:43:51 -0700 |
| commit | 0e37ff0d591dd75ceec9208196bec29efaec607a (patch) | |
| tree | c126fa823a1f3864e9c363aac70e3a3db0219957 /lib/std/Uri.zig | |
| parent | 0b3f0124dc33403d329fb8ee63a93215d9af1f1e (diff) | |
| download | zig-0e37ff0d591dd75ceec9208196bec29efaec607a.tar.gz zig-0e37ff0d591dd75ceec9208196bec29efaec607a.zip | |
std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API
make std.testing.expectFmt work at compile-time
std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.
Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
- anytype -> *std.io.Writer
- inferred error set -> error{WriteFailed}
- options -> (deleted)
* std.fmt.Formatted
- now takes context type explicitly
- no fmt string
Diffstat (limited to 'lib/std/Uri.zig')
| -rw-r--r-- | lib/std/Uri.zig | 98 |
1 files changed, 40 insertions, 58 deletions
diff --git a/lib/std/Uri.zig b/lib/std/Uri.zig index ee0c602125..b1dc845eb5 100644 --- a/lib/std/Uri.zig +++ b/lib/std/Uri.zig @@ -34,27 +34,22 @@ pub const Component = union(enum) { return switch (component) { .raw => |raw| raw, .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| - try std.fmt.allocPrint(arena, "{raw}", .{component}) + try std.fmt.allocPrint(arena, "{fraw}", .{component}) else percent_encoded, }; } - pub fn format( - component: Component, - comptime fmt_str: []const u8, - _: std.fmt.FormatOptions, - writer: anytype, - ) @TypeOf(writer).Error!void { + pub fn format(component: Component, w: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void { if (fmt_str.len == 0) { - try writer.print("std.Uri.Component{{ .{s} = \"{}\" }}", .{ + try w.print("std.Uri.Component{{ .{s} = \"{f}\" }}", .{ @tagName(component), - std.zig.fmtEscapes(switch (component) { + std.zig.fmtString(switch (component) { .raw, .percent_encoded => |string| string, }), }); } else if (comptime std.mem.eql(u8, fmt_str, "raw")) switch (component) { - .raw => |raw| try writer.writeAll(raw), + .raw => |raw| try w.writeAll(raw), .percent_encoded => |percent_encoded| { var start: usize = 0; var index: usize = 0; @@ -63,51 +58,47 @@ pub const Component = union(enum) { if (percent_encoded.len - index < 2) continue; const percent_encoded_char = std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue; - try writer.print("{s}{c}", .{ + try w.print("{s}{c}", .{ percent_encoded[start..percent], percent_encoded_char, }); start = percent + 3; index = percent + 3; } - try writer.writeAll(percent_encoded[start..]); + try w.writeAll(percent_encoded[start..]); }, } else if (comptime std.mem.eql(u8, fmt_str, "%")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isUnreserved), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isUnreserved), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "user")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isUserChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isUserChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "password")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isPasswordChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isPasswordChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "host")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isHostChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isHostChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "path")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isPathChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isPathChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "query")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isQueryChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isQueryChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else if (comptime std.mem.eql(u8, fmt_str, "fragment")) switch (component) { - .raw => |raw| try percentEncode(writer, raw, isFragmentChar), - .percent_encoded => |percent_encoded| try writer.writeAll(percent_encoded), + .raw => |raw| try percentEncode(w, raw, isFragmentChar), + .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } else @compileError("invalid format string '" ++ fmt_str ++ "'"); } - pub fn percentEncode( - writer: anytype, - raw: []const u8, - comptime isValidChar: fn (u8) bool, - ) @TypeOf(writer).Error!void { + pub fn percentEncode(w: *std.io.Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) std.io.Writer.Error!void { var start: usize = 0; for (raw, 0..) |char, index| { if (isValidChar(char)) continue; - try writer.print("{s}%{X:0>2}", .{ raw[start..index], char }); + try w.print("{s}%{X:0>2}", .{ raw[start..index], char }); start = index + 1; } - try writer.writeAll(raw[start..]); + try w.writeAll(raw[start..]); } }; @@ -247,11 +238,7 @@ pub const WriteToStreamOptions = struct { port: bool = true, }; -pub fn writeToStream( - uri: Uri, - options: WriteToStreamOptions, - writer: anytype, -) @TypeOf(writer).Error!void { +pub fn writeToStream(uri: Uri, writer: *std.io.Writer, options: WriteToStreamOptions) std.io.Writer.Error!void { if (options.scheme) { try writer.print("{s}:", .{uri.scheme}); if (options.authority and uri.host != null) { @@ -261,39 +248,34 @@ pub fn writeToStream( if (options.authority) { if (options.authentication and uri.host != null) { if (uri.user) |user| { - try writer.print("{user}", .{user}); + try writer.print("{fuser}", .{user}); if (uri.password) |password| { - try writer.print(":{password}", .{password}); + try writer.print(":{fpassword}", .{password}); } try writer.writeByte('@'); } } if (uri.host) |host| { - try writer.print("{host}", .{host}); + try writer.print("{fhost}", .{host}); if (options.port) { if (uri.port) |port| try writer.print(":{d}", .{port}); } } } if (options.path) { - try writer.print("{path}", .{ + try writer.print("{fpath}", .{ if (uri.path.isEmpty()) Uri.Component{ .percent_encoded = "/" } else uri.path, }); if (options.query) { - if (uri.query) |query| try writer.print("?{query}", .{query}); + if (uri.query) |query| try writer.print("?{fquery}", .{query}); } if (options.fragment) { - if (uri.fragment) |fragment| try writer.print("#{fragment}", .{fragment}); + if (uri.fragment) |fragment| try writer.print("#{ffragment}", .{fragment}); } } } -pub fn format( - uri: Uri, - comptime fmt_str: []const u8, - _: std.fmt.FormatOptions, - writer: anytype, -) @TypeOf(writer).Error!void { +pub fn format(uri: Uri, writer: *std.io.Writer, comptime fmt_str: []const u8) std.io.Writer.Error!void { const scheme = comptime std.mem.indexOfScalar(u8, fmt_str, ';') != null or fmt_str.len == 0; const authentication = comptime std.mem.indexOfScalar(u8, fmt_str, '@') != null or fmt_str.len == 0; const authority = comptime std.mem.indexOfScalar(u8, fmt_str, '+') != null or fmt_str.len == 0; @@ -301,14 +283,14 @@ pub fn format( const query = comptime std.mem.indexOfScalar(u8, fmt_str, '?') != null or fmt_str.len == 0; const fragment = comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null or fmt_str.len == 0; - return writeToStream(uri, .{ + return writeToStream(uri, writer, .{ .scheme = scheme, .authentication = authentication, .authority = authority, .path = path, .query = query, .fragment = fragment, - }, writer); + }); } /// Parses the URI or returns an error. @@ -447,7 +429,7 @@ test remove_dot_segments { fn merge_paths(base: Component, new: []u8, aux_buf: *[]u8) error{NoSpaceLeft}!Component { var aux = std.io.fixedBufferStream(aux_buf.*); if (!base.isEmpty()) { - try aux.writer().print("{path}", .{base}); + try aux.writer().print("{fpath}", .{base}); aux.pos = std.mem.lastIndexOfScalar(u8, aux.getWritten(), '/') orelse return remove_dot_segments(new); } @@ -812,7 +794,7 @@ test "Special test" { test "URI percent encoding" { try std.testing.expectFmt( "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad", - "{%}", + "{f%}", .{Component{ .raw = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad" }}, ); } @@ -822,7 +804,7 @@ test "URI percent decoding" { const expected = "\\ö/ äöß ~~.adas-https://canvas:123/#ads&&sad"; var input = "%5C%C3%B6%2F%20%C3%A4%C3%B6%C3%9F%20~~.adas-https%3A%2F%2Fcanvas%3A123%2F%23ads%26%26sad".*; - try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }}); + try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); var output: [expected.len]u8 = undefined; try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); @@ -834,7 +816,7 @@ test "URI percent decoding" { const expected = "/abc%"; var input = expected.*; - try std.testing.expectFmt(expected, "{raw}", .{Component{ .percent_encoded = &input }}); + try std.testing.expectFmt(expected, "{fraw}", .{Component{ .percent_encoded = &input }}); var output: [expected.len]u8 = undefined; try std.testing.expectEqualStrings(percentDecodeBackwards(&output, &input), expected); @@ -848,7 +830,7 @@ test "URI query encoding" { const parsed = try Uri.parse(address); // format the URI to percent encode it - try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{/?}", .{parsed}); + try std.testing.expectFmt("/?response-content-type=application%2Foctet-stream", "{f/?}", .{parsed}); } test "format" { @@ -862,7 +844,7 @@ test "format" { .query = null, .fragment = null, }; - try std.testing.expectFmt("file:/foo/bar/baz", "{;/?#}", .{uri}); + try std.testing.expectFmt("file:/foo/bar/baz", "{f;/?#}", .{uri}); } test "URI malformed input" { |
