fix mime.charsetString()

This commit is contained in:
Pierre Tachoire
2025-12-12 18:00:20 +01:00
parent 26827efe34
commit 42440f1503
4 changed files with 17 additions and 9 deletions

View File

@@ -24,6 +24,7 @@ pub const Mime = struct {
// IANA defines max. charset value length as 40. // IANA defines max. charset value length as 40.
// We keep 41 for null-termination since HTML parser expects in this format. // We keep 41 for null-termination since HTML parser expects in this format.
charset: [41]u8 = default_charset, charset: [41]u8 = default_charset,
charset_len: usize = 5,
/// String "UTF-8" continued by null characters. /// String "UTF-8" continued by null characters.
pub const default_charset = .{ 'U', 'T', 'F', '-', '8' } ++ .{0} ** 36; pub const default_charset = .{ 'U', 'T', 'F', '-', '8' } ++ .{0} ** 36;
@@ -53,7 +54,7 @@ pub const Mime = struct {
other: struct { type: []const u8, sub_type: []const u8 }, other: struct { type: []const u8, sub_type: []const u8 },
}; };
pub fn contentTypeString(mime: *const Mime) [:0]const u8 { pub fn contentTypeString(mime: *const Mime) []const u8 {
return switch (mime.content_type) { return switch (mime.content_type) {
.text_xml => "text/xml", .text_xml => "text/xml",
.text_html => "text/html", .text_html => "text/html",
@@ -66,8 +67,12 @@ pub const Mime = struct {
} }
/// Returns the null-terminated charset value. /// Returns the null-terminated charset value.
pub fn charsetString(mime: *const Mime) [:0]const u8 { pub fn charsetStringZ(mime: *const Mime) [:0]const u8 {
return @ptrCast(&mime.charset); return mime.charset[0..mime.charset_len :0];
}
pub fn charsetString(mime: *const Mime) []const u8 {
return mime.charset[0..mime.charset_len];
} }
/// Removes quotes of value if quotes are given. /// Removes quotes of value if quotes are given.
@@ -111,6 +116,7 @@ pub const Mime = struct {
const params = trimLeft(normalized[type_len..]); const params = trimLeft(normalized[type_len..]);
var charset: [41]u8 = undefined; var charset: [41]u8 = undefined;
var charset_len: usize = undefined;
var it = std.mem.splitScalar(u8, params, ';'); var it = std.mem.splitScalar(u8, params, ';');
while (it.next()) |attr| { while (it.next()) |attr| {
@@ -136,6 +142,7 @@ pub const Mime = struct {
@memcpy(charset[0..attribute_value.len], attribute_value); @memcpy(charset[0..attribute_value.len], attribute_value);
// Null-terminate right after attribute value. // Null-terminate right after attribute value.
charset[attribute_value.len] = 0; charset[attribute_value.len] = 0;
charset_len = attribute_value.len;
}, },
} }
} }
@@ -143,6 +150,7 @@ pub const Mime = struct {
return .{ return .{
.params = params, .params = params,
.charset = charset, .charset = charset,
.charset_len = charset_len,
.content_type = content_type, .content_type = content_type,
}; };
} }
@@ -523,9 +531,9 @@ fn expect(expected: Expectation, input: []const u8) !void {
if (expected.charset) |ec| { if (expected.charset) |ec| {
// We remove the null characters for testing purposes here. // We remove the null characters for testing purposes here.
try testing.expectEqual(ec, actual.charsetString()[0..ec.len]); try testing.expectEqual(ec, actual.charsetString());
} else { } else {
const m: Mime = .unknown; const m: Mime = .unknown;
try testing.expectEqual(m.charsetString(), actual.charsetString()); try testing.expectEqual(m.charsetStringZ(), actual.charsetStringZ());
} }
} }

View File

@@ -740,14 +740,14 @@ pub const Page = struct {
log.debug(.http, "navigate first chunk", .{ .content_type = mime.content_type, .len = data.len }); log.debug(.http, "navigate first chunk", .{ .content_type = mime.content_type, .len = data.len });
self.mode = switch (mime.content_type) { self.mode = switch (mime.content_type) {
.text_html => .{ .html = try parser.Parser.init(mime.charsetString()) }, .text_html => .{ .html = try parser.Parser.init(mime.charsetStringZ()) },
.application_json, .application_json,
.text_javascript, .text_javascript,
.text_css, .text_css,
.text_plain, .text_plain,
=> blk: { => blk: {
var p = try parser.Parser.init(mime.charsetString()); var p = try parser.Parser.init(mime.charsetStringZ());
try p.process("<html><head><meta charset=\"utf-8\"></head><body><pre>"); try p.process("<html><head><meta charset=\"utf-8\"></head><body><pre>");
break :blk .{ .text = p }; break :blk .{ .text = p };
}, },

View File

@@ -678,7 +678,7 @@ pub const XMLHttpRequest = struct {
} }
var fbs = std.io.fixedBufferStream(self.response_bytes.items); var fbs = std.io.fixedBufferStream(self.response_bytes.items);
const doc = parser.documentHTMLParse(fbs.reader(), mime.charsetString()) catch { const doc = parser.documentHTMLParse(fbs.reader(), mime.charsetStringZ()) catch {
self.response_obj = .{ .Failure = {} }; self.response_obj = .{ .Failure = {} };
return; return;
}; };

View File

@@ -412,7 +412,7 @@ const TransferAsResponseWriter = struct {
try jws.objectField("mimeType"); try jws.objectField("mimeType");
try jws.write(mime.contentTypeString()); try jws.write(mime.contentTypeString());
try jws.objectField("charset"); try jws.objectField("charset");
try jws.write(mime.charsetString()[0..]); try jws.write(mime.charsetString());
} }
{ {