Optimize PUB and HPUB parsing

This will try to take better advantage of the buffered reading.
Instead of pushing one byte at a time to the array list for each
section, find the end index for each section, then alloc the arraylist
and copy the data into it all at once.
This commit is contained in:
2026-01-05 19:47:08 -05:00
parent 3342aa22ab
commit 318d467f5c

View File

@@ -404,12 +404,14 @@ fn parseSub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_second;
},
.in_second => {
const byte = try in.peekByte();
if (!isWhitespace(byte)) {
try second.append(alloc, byte);
in.toss(1);
continue :sw .in_second;
}
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try second.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .after_second;
},
.after_second => {
@@ -424,13 +426,15 @@ fn parseSub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_third;
},
.in_third => {
const byte = try in.peekByte();
if (byte == '\r') {
continue :sw .in_end;
}
try third.?.append(alloc, byte);
in.toss(1);
continue :sw .in_third;
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try third.?.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .in_end;
},
.in_end => {
try expectStreamBytes(in, "\r\n");
@@ -674,12 +678,14 @@ fn parsePub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_second;
},
.in_second => {
const byte = try in.peekByte();
if (!isWhitespace(byte)) {
try second.append(alloc, byte);
in.toss(1);
continue :sw .in_second;
}
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try second.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .after_second;
},
.after_second => {
@@ -694,15 +700,15 @@ fn parsePub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_third;
},
.in_third => {
const byte = try in.peekByte();
if (byte == '\r') {
continue :sw .in_end;
} else if (isDigit(byte)) {
try third.?.append(alloc, byte);
in.toss(1);
continue :sw .in_third;
}
return error.InvalidStream;
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try third.?.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .in_end;
},
.in_end => {
try expectStreamBytes(in, "\r\n");
@@ -847,12 +853,14 @@ fn parseHPub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_second;
},
.in_second => {
const byte = try in.peekByte();
if (!isWhitespace(byte)) {
try second.append(alloc, byte);
in.toss(1);
continue :sw .in_second;
}
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try second.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .after_second;
},
.after_second => {
@@ -867,12 +875,14 @@ fn parseHPub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_third;
},
.in_third => {
const byte = try in.peekByte();
if (!isWhitespace(byte)) {
try third.append(alloc, byte);
in.toss(1);
continue :sw .in_third;
}
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try third.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .after_third;
},
.after_third => {
@@ -887,15 +897,15 @@ fn parseHPub(alloc: Allocator, in: *Reader) !Message {
continue :sw .in_fourth;
},
.in_fourth => {
const byte = try in.peekByte();
if (byte == '\r') {
continue :sw .in_end;
} else if (isDigit(byte)) {
try fourth.?.append(alloc, byte);
in.toss(1);
continue :sw .in_fourth;
}
return error.InvalidStream;
for (1..in.buffer.len) |i| {
try in.fill(i + 1);
if (isWhitespace(in.buffered()[i])) {
@memcpy(try fourth.?.addManyAsSlice(alloc, i), in.buffered()[0..i]);
in.toss(i);
break;
}
} else return error.EndOfStream;
continue :sw .in_end;
},
.in_end => {
try expectStreamBytes(in, "\r\n");