DoxigAlpha

decode

dest.len must be what you get from ::calcSize. Invalid characters result in error.InvalidCharacter. Invalid padding results in error.InvalidPadding.

Function parameters

Parameters

#
decoder:*const Base64Decoder
dest:[]u8
source:[]const u8

Base64 codecs

Types

#
Codecs
Base64 codecs

Error sets in this namespace

Error Sets

#

The Base64 alphabet defined in

Values

#
standard_alphabet_chars
The Base64 alphabet defined in
standard
Standard Base64 codecs, with padding, as defined in
standard_no_pad
Standard Base64 codecs, without padding, as defined in
url_safe_alphabet_chars
The URL-safe Base64 alphabet defined in
url_safe
URL-safe Base64 codecs, with padding, as defined in
url_safe_no_pad
URL-safe Base64 codecs, without padding, as defined in

Source

Implementation

#
pub fn decode(decoder: *const Base64Decoder, dest: []u8, source: []const u8) Error!void {
    if (decoder.pad_char != null and source.len % 4 != 0) return error.InvalidPadding;
    var dest_idx: usize = 0;
    var fast_src_idx: usize = 0;
    var acc: u12 = 0;
    var acc_len: u4 = 0;
    var leftover_idx: ?usize = null;
    while (fast_src_idx + 16 < source.len and dest_idx + 15 < dest.len) : ({
        fast_src_idx += 16;
        dest_idx += 12;
    }) {
        var bits: u128 = 0;
        inline for (0..4) |i| {
            var new_bits: u128 = decoder.fast_char_to_index[0][source[fast_src_idx + i * 4]];
            new_bits |= decoder.fast_char_to_index[1][source[fast_src_idx + 1 + i * 4]];
            new_bits |= decoder.fast_char_to_index[2][source[fast_src_idx + 2 + i * 4]];
            new_bits |= decoder.fast_char_to_index[3][source[fast_src_idx + 3 + i * 4]];
            if ((new_bits & invalid_char_tst) != 0) return error.InvalidCharacter;
            bits |= (new_bits << (24 * i));
        }
        std.mem.writeInt(u128, dest[dest_idx..][0..16], bits, .little);
    }
    while (fast_src_idx + 4 < source.len and dest_idx + 3 < dest.len) : ({
        fast_src_idx += 4;
        dest_idx += 3;
    }) {
        var bits = decoder.fast_char_to_index[0][source[fast_src_idx]];
        bits |= decoder.fast_char_to_index[1][source[fast_src_idx + 1]];
        bits |= decoder.fast_char_to_index[2][source[fast_src_idx + 2]];
        bits |= decoder.fast_char_to_index[3][source[fast_src_idx + 3]];
        if ((bits & invalid_char_tst) != 0) return error.InvalidCharacter;
        std.mem.writeInt(u32, dest[dest_idx..][0..4], bits, .little);
    }
    const remaining = source[fast_src_idx..];
    for (remaining, fast_src_idx..) |c, src_idx| {
        const d = decoder.char_to_index[c];
        if (d == invalid_char) {
            if (decoder.pad_char == null or c != decoder.pad_char.?) return error.InvalidCharacter;
            leftover_idx = src_idx;
            break;
        }
        acc = (acc << 6) + d;
        acc_len += 6;
        if (acc_len >= 8) {
            acc_len -= 8;
            dest[dest_idx] = @as(u8, @truncate(acc >> acc_len));
            dest_idx += 1;
        }
    }
    if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) {
        return error.InvalidPadding;
    }
    if (leftover_idx == null) return;
    const leftover = source[leftover_idx.?..];
    if (decoder.pad_char) |pad_char| {
        const padding_len = acc_len / 2;
        var padding_chars: usize = 0;
        for (leftover) |c| {
            if (c != pad_char) {
                return if (c == Base64Decoder.invalid_char) error.InvalidCharacter else error.InvalidPadding;
            }
            padding_chars += 1;
        }
        if (padding_chars != padding_len) return error.InvalidPadding;
    }
}