structstd.base64.Base64DecoderWithIgnore[src]

Fields

decoder: Base64Decoder
char_is_ignored: [256]bool

Functions

Functioninit[src]

pub fn init(alphabet_chars: [64]u8, pad_char: ?u8, ignore_chars: []const u8) Base64DecoderWithIgnore

Parameters

alphabet_chars: [64]u8
pad_char: ?u8
ignore_chars: []const u8

Source Code

Source code
pub fn init(alphabet_chars: [64]u8, pad_char: ?u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
    var result = Base64DecoderWithIgnore{
        .decoder = Base64Decoder.init(alphabet_chars, pad_char),
        .char_is_ignored = [_]bool{false} ** 256,
    };
    for (ignore_chars) |c| {
        assert(result.decoder.char_to_index[c] == Base64Decoder.invalid_char);
        assert(!result.char_is_ignored[c]);
        assert(result.decoder.pad_char != c);
        result.char_is_ignored[c] = true;
    }
    return result;
}

FunctioncalcSizeUpperBound[src]

pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize

Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding. InvalidPadding is returned if the input length is not valid.

Parameters

decoder_with_ignore: *const Base64DecoderWithIgnore
source_len: usize

Source Code

Source code
pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
    var result = source_len / 4 * 3;
    if (decoder_with_ignore.decoder.pad_char == null) {
        const leftover = source_len % 4;
        result += leftover * 3 / 4;
    }
    return result;
}

Functiondecode[src]

pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8) Error!usize

Invalid characters that are not ignored result in error.InvalidCharacter. Invalid padding results in error.InvalidPadding. Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound. Returns the number of bytes written to dest.

Parameters

decoder_with_ignore: *const Base64DecoderWithIgnore
dest: []u8
source: []const u8

Source Code

Source code
pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8) Error!usize {
    const decoder = &decoder_with_ignore.decoder;
    var acc: u12 = 0;
    var acc_len: u4 = 0;
    var dest_idx: usize = 0;
    var leftover_idx: ?usize = null;
    for (source, 0..) |c, src_idx| {
        if (decoder_with_ignore.char_is_ignored[c]) continue;
        const d = decoder.char_to_index[c];
        if (d == Base64Decoder.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) {
            if (dest_idx == dest.len) return error.NoSpaceLeft;
            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;
    }
    const padding_len = acc_len / 2;
    if (leftover_idx == null) {
        if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
        return dest_idx;
    }
    const leftover = source[leftover_idx.?..];
    if (decoder.pad_char) |pad_char| {
        var padding_chars: usize = 0;
        for (leftover) |c| {
            if (decoder_with_ignore.char_is_ignored[c]) continue;
            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;
    }
    return dest_idx;
}

Source Code

Source code
pub const Base64DecoderWithIgnore = struct {
    decoder: Base64Decoder,
    char_is_ignored: [256]bool,

    pub fn init(alphabet_chars: [64]u8, pad_char: ?u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
        var result = Base64DecoderWithIgnore{
            .decoder = Base64Decoder.init(alphabet_chars, pad_char),
            .char_is_ignored = [_]bool{false} ** 256,
        };
        for (ignore_chars) |c| {
            assert(result.decoder.char_to_index[c] == Base64Decoder.invalid_char);
            assert(!result.char_is_ignored[c]);
            assert(result.decoder.pad_char != c);
            result.char_is_ignored[c] = true;
        }
        return result;
    }

    /// Return the maximum possible decoded size for a given input length - The actual length may be less if the input includes padding.
    /// `InvalidPadding` is returned if the input length is not valid.
    pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) Error!usize {
        var result = source_len / 4 * 3;
        if (decoder_with_ignore.decoder.pad_char == null) {
            const leftover = source_len % 4;
            result += leftover * 3 / 4;
        }
        return result;
    }

    /// Invalid characters that are not ignored result in error.InvalidCharacter.
    /// Invalid padding results in error.InvalidPadding.
    /// Decoding more data than can fit in dest results in error.NoSpaceLeft. See also ::calcSizeUpperBound.
    /// Returns the number of bytes written to dest.
    pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8) Error!usize {
        const decoder = &decoder_with_ignore.decoder;
        var acc: u12 = 0;
        var acc_len: u4 = 0;
        var dest_idx: usize = 0;
        var leftover_idx: ?usize = null;
        for (source, 0..) |c, src_idx| {
            if (decoder_with_ignore.char_is_ignored[c]) continue;
            const d = decoder.char_to_index[c];
            if (d == Base64Decoder.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) {
                if (dest_idx == dest.len) return error.NoSpaceLeft;
                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;
        }
        const padding_len = acc_len / 2;
        if (leftover_idx == null) {
            if (decoder.pad_char != null and padding_len != 0) return error.InvalidPadding;
            return dest_idx;
        }
        const leftover = source[leftover_idx.?..];
        if (decoder.pad_char) |pad_char| {
            var padding_chars: usize = 0;
            for (leftover) |c| {
                if (decoder_with_ignore.char_is_ignored[c]) continue;
                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;
        }
        return dest_idx;
    }
}