Search results

There are no results.

std.base64.Decoder

class 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 code
Hide 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 code
Hide 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 code
Hide 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'