Remove an allocation when decoding base64

This commit is contained in:
anon 2024-04-19 01:20:08 +02:00
parent 97313ae98e
commit a2bec4b4fa
1 changed files with 19 additions and 10 deletions

29
email.d
View File

@ -9,6 +9,9 @@ pragma(lib, "curl");
import std.base64;
import std.string;
import std.range;
import std.utf;
import std.array;
import std.algorithm.iteration;
import arsd.characterencodings;
@ -866,18 +869,10 @@ class IncomingEmailMessage {
break;
case "base64":
if(textMessageBody.length) {
// alas, phobos' base64 decoder cannot accept ranges, so we have to allocate here
char[] mmb;
mmb.reserve(textMessageBody.length);
foreach (char ch; textMessageBody) if (ch > ' ' && ch < 127) mmb ~= ch;
textMessageBody = convertToUtf8Lossy(Base64.decode(mmb), charset);
textMessageBody = textMessageBody.decodeBase64Mime.convertToUtf8Lossy(charset);
}
if(htmlMessageBody.length) {
// alas, phobos' base64 decoder cannot accept ranges, so we have to allocate here
char[] mmb;
mmb.reserve(htmlMessageBody.length);
foreach (char ch; htmlMessageBody) if (ch > ' ' && ch < 127) mmb ~= ch;
htmlMessageBody = convertToUtf8Lossy(Base64.decode(mmb), charset);
htmlMessageBody = htmlMessageBody.decodeBase64Mime.convertToUtf8Lossy(charset);
}
break;
@ -1172,6 +1167,20 @@ string encodeBase64Mime(const(ubyte[]) content, string LINESEP = "\r\n") {
return cast(immutable(char[]))content.chunks(SOURCE_CHUNK_LENGTH).base64encode.join(LINESEP);
}
/// Base64 range decoder UFCS helper.
alias base64decode = Base64.decoder;
/// Base64 decoder, ignoring linebreaks which are mandated by RFC2045
immutable(ubyte[]) decodeBase64Mime(string encodedPart) {
return cast(immutable(ubyte[])) encodedPart
.byChar // prevent Autodecoding, which will break Base64 decoder. Since its base64, it's guarenteed to be 7bit ascii
.filter!((c) => c != '\r')
.splitter!((c) => c == '\n')
.joiner
.base64decode
.array;
}
/+
void main() {
import std.file;