///|
/// Base64-encode `data` for MIME: the output is split into lines of exactly
/// 76 characters separated by CRLF (MM_ENCOD_002, RFC 2045 section 6.8).
/// Uses the `gmlewis/base64` standard encoding as a dependency.
pub fn base64_mime_encode(data : Bytes) -> String {
  let encoded = @base64.std_encode2str(data.to_fixedarray())
  let src = string_to_bytes(encoded)
  let out = FixedArray::make(src.length() + src.length() / 76 * 2 + 2, b'\x00')
  let mut j = 0
  let mut col = 0
  for i = 0; i < src.length(); i = i + 1 {
    if col == 76 {
      out[j] = b'\r'
      out[j + 1] = b'\n'
      j += 2
      col = 0
    }
    out[j] = src[i]
    j += 1
    col += 1
  }
  bytes_to_string(Bytes::from_iter(out.iter())[0:j].to_owned())
}

///|
/// Base64-decode MIME text (whitespace/newlines tolerated, per RFC 2045).
pub fn base64_mime_decode(text : String) -> Bytes raise MailFailure {
  // strip CR, LF, spaces and tabs
  let src = string_to_bytes(text)
  let cleaned = FixedArray::make(src.length(), b'\x00')
  let mut j = 0
  for i = 0; i < src.length(); i = i + 1 {
    if src[i] != b'\r' && src[i] != b'\n' && src[i] != b' ' && src[i] != b'\t' {
      cleaned[j] = src[i]
      j += 1
    }
  }
  let cleaned_text = fixedarray_to_string(cleaned, j)
  @base64.std_decode2bytes(cleaned_text) catch {
    _ => raise MailFailure::encode("invalid base64")
  }
}