Browse the docs

silk.encoding.base64.

Encode and decode standard Base64 (RFC 4648, with padding) into byte slices that you supply.

When to use#

Use Base64 when a protocol needs the standard alphabet (A-Z, a-z, 0-9, +, /) with = padding, for example HTTP Basic authentication or a JSON field. Call Base64.encodedLength or Base64.decodedLength to get the exact size of the output, and then Base64.encodeInto or Base64.decodeInto to write it.

Details#

The functions do not allocate. They return a Result, and they check all input and the size of the output before they write the first byte. A failure does not change the output. A success changes only the prefix that it reports.

Decoding is strict. It rejects whitespace, the URL-safe characters - and _, missing or misplaced padding, and unused bits that are not zero, so each byte sequence has exactly one encoding.

Errors#

The functions return a Base64Error. Its reason tells you what failed, and offset gives the position in the input for a decoding error.

Gotchas#

This module has no MIME, PEM, URL-safe, unpadded, or streaming variant. Base64 is an encoding, not encryption.

Examples#

Encode and decode a short message#

silk
import silk.encoding.base64 { Base64, Base64Error }
import silk.core.result { Result }

pub fn main() -> i32 {
  let mut encoded: [u8; 8] = [0; 8]
  let written = match Base64.encodeInto(&mut encoded, b"Hi!?") {
    Result<usize, Base64Error>.Success { value } => value
    Result<usize, Base64Error>.Failure { error: _ } => {
      return 1
    }
  }
  // "Hi!?" encodes to "SGkhPw==".
  if written != 8 || encoded[0] != 83 || encoded[6] != 61 {
    return 1
  }
  let mut decoded: [u8; 4] = [0; 4]
  return match Base64.decodeInto(&mut decoded, &encoded) {
    Result<usize, Base64Error>.Success { value } => {
      if value != 4 || decoded[0] != 72 || decoded[3] != 63 {
        return 1
      }
      return 0
    }
    Result<usize, Base64Error>.Failure { error: _ } => 1
  }
}

Reject input that is not strict Base64#

silk
import silk.encoding.base64 { Base64, Base64Error, Base64Reason }
import silk.core.option { Option }
import silk.core.result { Result }

pub fn main() -> i32 {
  // `-` is URL-safe Base64, not standard Base64.
  return match Base64.decodedLength(b"ab-d") {
    Result<usize, Base64Error>.Failure { error } => {
      if error.reason != Base64Reason.InvalidByte
        || Option<usize>.unwrapOr(move error.offset, 0) != 2 {
        return 1
      }
      return 0
    }
    Result<usize, Base64Error>.Success { value: _ } => 1
  }
}

Import as Base64 with import silk.encoding.base64 { Base64 }.

Public declarations: 3.

Base64Reason#

silk
pub enum Base64Reason

The cause of a Base64Error.

InvalidLength#

silk
InvalidLength

The encoded input is not empty and its length is not a multiple of 4. offset is the input length.

InvalidByte#

silk
InvalidByte

An input byte is not in the standard alphabet. offset is its position.

InvalidPadding#

silk
InvalidPadding

= occurs before the last two positions, or = is followed by a byte that is not =. offset is the position of the misplaced =, or the input length.

NonCanonicalPadBits#

silk
NonCanonicalPadBits

The last character before the padding has unused bits that are not zero, such as QR== in place of QQ==. offset is its position.

SizeOverflow#

silk
SizeOverflow

The encoded length does not fit in usize.

OutputTooSmall#

silk
OutputTooSmall

The output slice is too short. required and available give the two lengths.

Implementation Debug for Base64Reason#

silk
impl Debug for Base64Reason

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as InvalidLength.

Base64Error#

silk
pub struct Base64Error

A Base64 failure.

Decoding errors set offset. OutputTooSmall sets required and available. The fields that do not apply to the reason are None.

Field reason#

silk
pub reason: Base64Reason

The cause of the failure.

Field offset#

silk
pub offset: Option<usize>

For a decoding error, the position in the input: the bad byte for InvalidByte and NonCanonicalPadBits, the misplaced = or the input length for InvalidPadding, and the input length for InvalidLength.

Field required#

silk
pub required: Option<usize>

For OutputTooSmall, the number of bytes that the output needs.

Field available#

silk
pub available: Option<usize>

For OutputTooSmall, the length of the output that you gave.

Implementation Debug for Base64Error#

silk
impl Debug for Base64Error

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the fields, as Base64Error { reason: ..., offset: ..., ... }.

Base64#

silk
pub struct Base64

Functions for strict standard Base64 with padding (RFC 4648).

When to use#

Use it when a protocol needs the standard alphabet (A-Z, a-z, 0-9, +, /) with = padding, for example HTTP Basic authentication or a JSON field. Call Base64.encodedLength or Base64.decodedLength to get the exact size of the output, and then Base64.encodeInto or Base64.decodeInto to write it.

Details#

The functions do not allocate. They check all input and the size of the output before they write the first byte. A failure does not change the output. Decoding is strict. It rejects whitespace, the URL-safe characters - and _, missing or misplaced padding, and unused bits that are not zero.

Gotchas#

There is no MIME, PEM, URL-safe, unpadded, or streaming variant. Base64 is an encoding, not encryption.

Implementation Base64#

silk
impl Base64

Associated function encodedLength#

silk
pub fn encodedLength(inputLength: usize) -> Result<usize, Base64Error>

Returns the length of the Base64 text for inputLength bytes: 4 for each started group of 3 bytes.

Returns 0 for 0.

Errors#

  • SizeOverflow if the length does not fit in usize.

Associated function decodedLength#

silk
pub fn decodedLength(input: &[u8]) -> Result<usize, Base64Error>

Checks that input is strict Base64 and returns the number of bytes that it decodes to.

Returns 0 for empty input. Use it to size the output of Base64.decodeInto.

Decoding is strict. It rejects whitespace, the URL-safe characters - and _, missing or misplaced padding, and unused bits that are not zero, so each byte sequence has exactly one encoding.

Errors#

  • InvalidLength, InvalidByte, InvalidPadding, or NonCanonicalPadBits for the first problem in input, from left to right. offset gives its position.

Associated function encodeInto#

silk
pub fn encodeInto(output: &mut [u8], input: &[u8]) -> Result<usize, Base64Error>

Writes the Base64 text of input to the start of output and returns the number of bytes written.

It writes no NUL terminator. The bytes of output after the written prefix do not change.

Errors#

  • SizeOverflow if the encoded length does not fit in usize.

  • OutputTooSmall if output is shorter than Base64.encodedLength. output does not change.

Associated function decodeInto#

silk
pub fn decodeInto(output: &mut [u8], input: &[u8]) -> Result<usize, Base64Error>

Decodes the Base64 text input to the start of output and returns the number of bytes written.

The bytes of output after the written prefix do not change.

Decoding is strict. It rejects whitespace, the URL-safe characters - and _, missing or misplaced padding, and unused bits that are not zero, so each byte sequence has exactly one encoding.

Errors#

  • InvalidLength, InvalidByte, InvalidPadding, or NonCanonicalPadBits if input is not strict Base64. These errors come before OutputTooSmall.

  • OutputTooSmall if output is shorter than Base64.decodedLength.

output does not change when an error occurs.

Category: Data formats.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page