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
- empty (Constant)
- formatEscaped (Function)
- formatFragment (Function)
- formatHost (Function)
- formatPassword (Function)
- formatPath (Function)
- formatQuery (Function)
- formatRaw (Function)
- formatUser (Function)
- isEmpty (Function)
- percentEncode (Function)
- toRaw (Function)
- toRawMaybeAlloc (Function)
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..]);
}
}