nomsu/lib/base64.nom

51 lines
2.2 KiB
Plaintext

#!/usr/bin/env nomsu -V4.12.12.8
#
This file defines actions for encoding/decoding base 64, as specified in:
https://tools.ietf.org/html/rfc4648
%b64_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
%b64_chars = [: for % in 1 to (size of %b64_str): add (%b64_str::character %)]
%reverse_b64 = {: for %c in %b64_chars at %i: add %c = (%i - 1)}
%reverse_b64."=" = 64
set %reverse_b64's metatable to {__index: -> 0}
test:
%cases = ["", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy"]
for %len = %encoded in %cases:
%plain = ("foobar"::from 1 to (%len - 1))
assume (base64 %plain) == %encoded
assume (base64 decode %encoded) == %plain
externally [base64 %str, base64 encode %str, %str base64] all mean:
%chars = []
for %i in 1 to (size of %str) via 3:
%bytes = [=lua "\%str:byte(\%i, \(%i + 2))"]
%chars::add %b64_chars.(((%bytes.1 & 252) >> 2) + 1)
if (size of %bytes) is:
3:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1)
%chars::add %b64_chars.(((%bytes.2 & 15) << 2) + ((%bytes.3 & 192) >> 6) + 1)
%chars::add %b64_chars.((%bytes.3 & 63) + 1)
2:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1)
%chars::add %b64_chars.(((%bytes.2 & 15) << 2) + 1)
%chars::add "="
1:
%chars::add %b64_chars.(((%bytes.1 & 3) << 4) + 1)
%chars::add "="
%chars::add "="
return (%chars::joined)
externally (chr %) means (=lua "string.char(\%)")
externally [decode base64 %str, %str base64 decoded, base64 decode %str] all mean:
%chars = []
for %i in 1 to (size of %str) via 4:
%indices = [: for %j in %i to (%i + 3): add %reverse_b64.(%str::character %j)]
%chars::add (chr ((%indices.1 << 2) + ((%indices.2 & 48) >> 4)))
if ((%str::character (%i + 2)) == "="): stop
%chars::add (chr (((%indices.2 & 15) << 4) + ((%indices.3 & 60) >> 2)))
if ((%str::character (%i + 3)) == "="): stop
%chars::add (chr (((%indices.3 & 3) << 6) + %indices.4))
return (%chars::joined)