union Component [src]

Fields

raw: []const u8Invalid characters in this component must be percent encoded before being printed as part of a URI.
percent_encoded: []const u8This component is already percent-encoded, it can be printed directly as part of a URI.

Members

Source

pub const Component = union(enum) { /// Invalid characters in this component must be percent encoded /// before being printed as part of a URI. raw: []const u8, /// This component is already percent-encoded, it can be printed /// directly as part of a URI. percent_encoded: []const u8, pub const empty: Component = .{ .percent_encoded = "" }; pub fn isEmpty(component: Component) bool { return switch (component) { .raw, .percent_encoded => |string| string.len == 0, }; } /// Returned value may point into `buffer` or be the original string. pub fn toRaw(component: Component, buffer: []u8) error{NoSpaceLeft}![]const u8 { return switch (component) { .raw => |raw| raw, .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| try std.fmt.bufPrint(buffer, "{f}", .{std.fmt.alt(component, .formatRaw)}) else percent_encoded, }; } /// Allocates the result with `arena` only if needed, so the result should not be freed. pub fn toRawMaybeAlloc(component: Component, arena: Allocator) Allocator.Error![]const u8 { return switch (component) { .raw => |raw| raw, .percent_encoded => |percent_encoded| if (std.mem.indexOfScalar(u8, percent_encoded, '%')) |_| try std.fmt.allocPrint(arena, "{f}", .{std.fmt.alt(component, .formatRaw)}) else percent_encoded, }; } pub fn formatRaw(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try w.writeAll(raw), .percent_encoded => |percent_encoded| { var start: usize = 0; var index: usize = 0; while (std.mem.indexOfScalarPos(u8, percent_encoded, index, '%')) |percent| { index = percent + 1; if (percent_encoded.len - index < 2) continue; const percent_encoded_char = std.fmt.parseInt(u8, percent_encoded[index..][0..2], 16) catch continue; try w.print("{s}{c}", .{ percent_encoded[start..percent], percent_encoded_char, }); start = percent + 3; index = percent + 3; } try w.writeAll(percent_encoded[start..]); }, } } pub fn formatEscaped(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isUnreserved), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatUser(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isUserChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatPassword(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isPasswordChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatHost(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isHostChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatPath(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isPathChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatQuery(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isQueryChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn formatFragment(component: Component, w: *Writer) Writer.Error!void { switch (component) { .raw => |raw| try percentEncode(w, raw, isFragmentChar), .percent_encoded => |percent_encoded| try w.writeAll(percent_encoded), } } pub fn percentEncode(w: *Writer, raw: []const u8, comptime isValidChar: fn (u8) bool) Writer.Error!void { var start: usize = 0; for (raw, 0..) |char, index| { if (isValidChar(char)) continue; try w.print("{s}%{X:0>2}", .{ raw[start..index], char }); start = index + 1; } try w.writeAll(raw[start..]); } }