今回はワンライナーでBase64
エンコーダを実装しようと思います。
発端は、「以前自分が書いたなんかよくわからないけどバグっていることだけはわかるD言語で書いたBase64
エンコーダ」を見つけてしまい、しかもそのコードが汚かったので"イケメン"な感じで書いてみようと思って書いてみました。
Wikipedia
のBase64
の項に書かれている仕様をそのままコードに落としただけなので解説はしません。
では、以下にD言語での一般的なBase64エンコーダのコードを貼っておきます。
import std.algorithm,
std.string,
std.ascii,
std.range,
std.conv;
R delegate(Args) Z(R, Args...)(R delegate(R delegate(Args), Args) f){
return (Args args) => f(Z(f), args);
}
string encode(T)(T data) {
return
(convb =>
(table =>
(converted =>
(binaries =>
(bLen =>
(prepared =>
(pLen =>
(quotients =>
pLen % 4 == 0
? quotients
: quotients ~ (remainds =>
remainds.map!(remain =>
table[remain]
).array.join ~ repeat("=", 4 - (pLen % 4)).join
)(prepared[($ - (pLen % 4))..$])
)(
(pLen / 4).iota.map!(i =>
(j =>
4.iota.map!(k =>
table[prepared[j + k]]
).array.join
)(i * 4)
).array.join
)
)(prepared.length)
)(
(quotients =>
bLen % 6 == 0
? quotients
: quotients ~ (remainds =>
remainds ~ repeat("0", 6 - remainds.length).join
)(binaries[($ - (bLen % 6))..$])
)((bLen / 6).iota.map!(i => binaries[(i * 6)..((i + 1) * 6)]).array)
)
)(binaries.length)
)(converted.join)
)(data.map!(i =>
(e =>
e.length == 8
? e
: repeat("0", 8 - e.length).join ~ e
)(convb(i, 2))).array
)
)((charset =>
assocArray(
zip(
charset.length.iota.map!(i =>
(e =>
e.length == 6
? e
: repeat("0", 6 - e.length).join ~ e
)(convb(i, 2))),
charset))
)((uppercase ~ lowercase ~ digits ~ "+/").split(string.init))
)
)((ulong N, int base) =>
(convbM =>
convbM(N, N, [], base)
)(Z((string delegate(ulong, ulong, ulong[], int base) convbM, ulong N, ulong tmp, ulong[] stack, int base) =>
tmp ? convbM(N, tmp / base, stack ~ (tmp % base), base) : stack.reverse.map!(e => e.to!string).join)));
}