std.base64.Decoder
type pub Decoder
A type for decoding a base64 encoded sequence of bytes into a raw sequence of bytes.
By default, padding is expected and input of which the size isn't a multiple
of 4 is rejected. You can disable this by setting Decoder.padding
to
false
:
import std.base64 (Decoder)
let dec = Decoder.new
dec.padding = false
Examples
Using the standard alphabet:
import std.base64 (Decoder)
let plain = ByteArray.new
Decoder.new.decode('8J+Ygw=='.to_byte_array, into: plain)
plain.into_string # => '😃'
Using the URL safe alphabet:
import std.base64 (Decoder)
let plain = ByteArray.new
Decoder.url_safe.decode('8J-Ygw=='.to_byte_array, into: plain)
plain.into_string # => '😃'
Fields
padding
let pub @padding: Bool
If padding is required or not.
Static methods
new
Show source codeHide source code
fn pub static new -> Decoder {
Decoder(
table0: DECODE_STD.get(0),
table1: DECODE_STD.get(1),
table2: DECODE_STD.get(2),
table3: DECODE_STD.get(3),
padding: true,
)
}
fn pub static new -> Decoder
url_safe
Show source codeHide source code
fn pub static url_safe -> Decoder {
Decoder(
table0: DECODE_URL.get(0),
table1: DECODE_URL.get(1),
table2: DECODE_URL.get(2),
table3: DECODE_URL.get(3),
padding: true,
)
}
fn pub static url_safe -> Decoder
Instance methods
decode
Show source codeHide source code
fn pub decode(
input: ref ByteArray,
into: mut ByteArray,
) -> Result[Nil, DecodeError] {
if input.empty? { return Result.Ok(nil) }
let mut size = input.size
if @padding {
if size < 4 or (size % 4 != 0) { throw DecodeError.InvalidSize }
if input.get(size - 1) == PAD {
size -= 1
if input.get(size - 1) == PAD { size -= 1 }
}
}
let t0 = @table0
let t1 = @table1
let t2 = @table2
let t3 = @table3
let leftover = size % 4
let chunks = if leftover == 0 { size / 4 - 1 } else { size / 4 }
let mut i = 0
let mut y = 0
while i < chunks {
let a = t0.get(input.get(y))
let b = t1.get(input.get(y + 1))
let c = t2.get(input.get(y + 2))
let d = t3.get(input.get(y + 3))
let x = a | b | c | d
if x >= ERR_CHAR {
throw DecodeError.InvalidCharacter(first_invalid(y, a, b, c, d))
}
into.push(x & LO_MASK)
into.push(x & MI_MASK >> 8)
into.push(x & HI_MASK >> 16)
i += 1
y += 4
}
match leftover {
case 0 -> {
let a = t0.get(input.get(y))
let b = t1.get(input.get(y + 1))
let c = t2.get(input.get(y + 2))
let d = t3.get(input.get(y + 3))
let x = a | b | c | d
if x >= ERR_CHAR {
throw DecodeError.InvalidCharacter(first_invalid(y, a, b, c, d))
}
into.push(x & LO_MASK)
into.push(x & MI_MASK >> 8)
into.push(x & HI_MASK >> 16)
}
case 1 -> {
let x = t0.get(input.get(y))
if x >= ERR_CHAR { throw DecodeError.InvalidCharacter(y) }
into.push(x & LO_MASK)
}
case 2 -> {
let a = t0.get(input.get(y))
let b = t1.get(input.get(y + 1))
let x = a | b
if x >= ERR_CHAR {
throw DecodeError.InvalidCharacter(first_invalid(y, a, b, 0, 0))
}
into.push(x & LO_MASK)
}
case _ -> {
let a = t0.get(input.get(y))
let b = t1.get(input.get(y + 1))
let c = t2.get(input.get(y + 2))
let x = a | b | c
if x >= ERR_CHAR {
throw DecodeError.InvalidCharacter(first_invalid(y, a, b, c, 0))
}
into.push(x & LO_MASK)
into.push(x & MI_MASK >> 8)
}
}
Result.Ok(nil)
}
fn pub decode(input: ref ByteArray, into: mut ByteArray) -> Result[Nil, DecodeError]
Decodes a sequence of base64 encoded bytes.
Errors
A DecodeError
is returned if:
- Padding is required, but the input size isn't a multiple of 4
- The input contains invalid characters (e.g. whitespace)
Examples
import std.base64 (Decoder, Encoder)
let base64 = ByteArray.new
let plain = ByteArray.new
Encoder.new.encode('hello world'.to_byte_array, into: base64)
base64.to_string # => 'aGVsbG8gd29ybGQ='
Decoder.new.decode(base64, into: plain) # => Result.Ok(nil)
plain.into_string # => 'hello world'