aboutsummaryrefslogtreecommitdiff
path: root/lib/base64/init.nom
blob: 52575193e67a16443cc9a54b7124b29f5c4452bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env nomsu -V6.15.13.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 (#$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

external:
    [base64 $str, base64 encode $str, $str base64] all mean:
        $chars = []
        for $i in 1 to (#$str) via 3:
            $bytes = [=lua "\$str:byte(\$i, \($i + 2))"]
            $chars, add $b64_chars.((($bytes.1 & 252) >> 2) + 1)
            if (#$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)
    (chr $) means (=lua "string.char(\$)")
    [decode base64 $str, $str base64 decoded, base64 decode $str] all mean:
        $chars = []
        for $i in 1 to (#$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)