#! lua
local char in string
local pairs = pairs
-- module "base64" -- exports encode,decode
local C = { } -- encryption table
for i = 0,25 do
 C[i],C[26+i]  = char(65+i),char(97+i)  -- upper/lower case letters
end
for i = 52,61 do C[i] = char(i-4) end -- digits
C[62], C[63] = '-', '_'

local encode = \(data)
   local bb,x,fmt,r = { },  "", ('%s'):rep(5)
   for s = 0,#data - 1,3 do
     for b = 1,3 do bb[b] = (data:sub(s+b)):byte() or 0 end
     r = #data - s
     x = fmt:format(x,
                    C[bb[1]>>2],
                    C[((bb[1]%4)<<4)|(bb[2]>>4)] or "=",
                    r>1 and C[((bb[2]%16)<<2)|(bb[3]>>6)] or "=",
                    r>2 and C[bb[3]%64] or "=")
    end -- for
    => x end -- function

local B = { } -- decryption table
for i,v in pairs(C) do B[v] = i end -- for

local decode = \(data)
   local cc,y,fmt,n,j = { }, "", ('%s'):rep(4), 256
   for d=0,#data - 1,4 do
    for c=1,4 do j = d+c
        cc[c] = B[data:sub(j,j) or "="] end -- for
    y = fmt:format(y,
                   char(((cc[1]<<2)%n)|(cc[2]>>4)),
                   cc[3] and char(((cc[2]<<4)%n)|(cc[3]>>2)) or "",
                   cc[4] and char((((cc[3]<<6)%n)%192)|cc[4]) or "")
  end -- for
  => y end -- function

=> { encode = encode, decode = decode, }
