blob: 4b8ae540ae9a44c045b6ea0bb2396c456b561bf2 (
plain) (
tree)
|
|
import std/base64
import js/domexception
import types/opt
# atob and btoa convert Latin-1 to base64 and vice versa. (And throw on
# anything above latin-1.)
# We could do this quite efficiently if we had an API for the QuickJS string
# internal representation. Unfortunately we do not, so we do the following:
# * atob: decode, convert latin-1 to utf-8, pass to qjs, where it is then
# converted to latin-1 again.
# * btoa: qjs converts its string (either utf-16 or latin-1) to utf-8,
# we convert this to latin-1 (or throw), then encode.
# That is two conversions more than needed (i.e. 0) for each step. We should
# really write an API for handling QJS strings sometime...
proc atob*(data: string): DOMResult[string] =
try:
let ds = base64.decode(data)
var s = newStringOfCap(ds.len)
for c in ds:
if uint8(c) <= 0x7F:
s &= c
else: # latin-1
s &= char((uint8(c) shr 6) or 0xC0)
s &= char((uint8(c) and 0x3F) or 0x80)
return ok(s)
except ValueError:
return err(newDOMException("Invalid character in string",
"InvalidCharacterError"))
proc btoa*(data: string): DOMResult[string] =
var s = newStringOfCap(data.len)
var i = 0
while i < data.len:
let c = data[i]
let n = uint8(c)
if n <= 0x7F: # ascii
s &= c
inc i
elif n <= 0xC3: # latin-1
inc i
s &= char((n shl 6) or (uint8(data[i]) and 0x3F))
inc i
else:
return err(newDOMException("Invalid character in string",
"InvalidCharacterError"))
return ok(base64.encode(s))
|