diff options
Diffstat (limited to 'src/base64/base64.zig')
-rw-r--r-- | src/base64/base64.zig | 92 |
1 files changed, 41 insertions, 51 deletions
diff --git a/src/base64/base64.zig b/src/base64/base64.zig index daf5b228e..0cd16fb8c 100644 --- a/src/base64/base64.zig +++ b/src/base64/base64.zig @@ -5,34 +5,28 @@ pub const DecodeResult = struct { fail: bool = false, }; -pub fn decode(destination: []u8, source: []const u8) DecodeResult { - var wrote: usize = 0; - const result = zig_base64.standard.decoderWithIgnore(&[_]u8{ - ' ', - '\n', - '\r', - '\t', +const mixed_decoder = brk: { + var decoder = zig_base64.standard.decoderWithIgnore("\xff \t\r\n" ++ [_]u8{ std.ascii.control_code.vt, - }).decode(destination, source, &wrote) catch { - return .{ - .written = wrote, - .fail = true, - }; - }; + std.ascii.control_code.ff, + }); - return .{ .written = result, .fail = false }; -} + for (zig_base64.url_safe_alphabet_chars[62..], 62..) |c, i| { + decoder.decoder.char_to_index[c] = @intCast(u8, i); + } -pub fn decodeURLSafe(destination: []u8, source: []const u8) DecodeResult { + break :brk decoder; +}; + +pub fn decode(destination: []u8, source: []const u8) DecodeResult { var wrote: usize = 0; - const result = urlsafe.decode(destination, source, &wrote) catch { + mixed_decoder.decode(destination, source, &wrote) catch { return .{ .written = wrote, .fail = true, }; }; - - return .{ .written = result, .fail = false }; + return .{ .written = wrote, .fail = false }; } pub fn encode(destination: []u8, source: []const u8) usize { @@ -58,14 +52,6 @@ pub fn encodeLen(source: anytype) usize { return zig_base64.standard.Encoder.calcSize(source.len); } -pub const urlsafe = zig_base64.Base64DecoderWithIgnore.init( - zig_base64.url_safe_alphabet_chars, - null, - "= \t\r\n" ++ [_]u8{ std.ascii.control_code.vt, std.ascii.control_code.ff }, -); - -pub const urlsafeEncoder = zig_base64.url_safe_no_pad.Encoder; - // This is just std.base64 copy-pasted // with support for returning how many bytes were decoded const zig_base64 = struct { @@ -118,7 +104,7 @@ const zig_base64 = struct { pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; fn urlSafeBase64DecoderWithIgnore(ignore: []const u8) Base64DecoderWithIgnore { - return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, null, ignore); + return Base64DecoderWithIgnore.init(url_safe_alphabet_chars, '=', ignore); } /// URL-safe Base64 codecs, with padding @@ -316,7 +302,7 @@ const zig_base64 = struct { /// 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 { + pub fn calcSizeUpperBound(decoder_with_ignore: *const Base64DecoderWithIgnore, source_len: usize) usize { var result = source_len / 4 * 3; if (decoder_with_ignore.decoder.pad_char == null) { const leftover = source_len % 4; @@ -329,7 +315,7 @@ const zig_base64 = struct { /// 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, wrote: *usize) Error!usize { + pub fn decode(decoder_with_ignore: *const Base64DecoderWithIgnore, dest: []u8, source: []const u8, wrote: *usize) Error!void { const decoder = &decoder_with_ignore.decoder; var acc: u12 = 0; var acc_len: u4 = 0; @@ -337,16 +323,21 @@ const zig_base64 = struct { var leftover_idx: ?usize = null; defer { - wrote.* = leftover_idx orelse dest_idx; + wrote.* = dest_idx; } 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; + if (decoder.pad_char) |pad_char| { + if (c == pad_char) { + leftover_idx = src_idx; + break; + } + } + if (decoder_with_ignore.char_is_ignored[Base64Decoder.invalid_char]) continue; + return error.InvalidCharacter; } acc = (acc << 6) + d; acc_len += 6; @@ -357,27 +348,26 @@ const zig_base64 = struct { 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; - } - var leftover = source[leftover_idx.?..]; + if (acc_len > 4 or (acc & (@as(u12, 1) << acc_len) - 1) != 0) return error.InvalidPadding; + 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; + const padding_len = acc_len / 2; + + if (leftover_idx) |idx| { + var leftover = source[idx..]; + 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; } - padding_chars += 1; + if (padding_chars != padding_len) return error.InvalidPadding; + } else if (padding_len > 0) { + return error.InvalidPadding; } - if (padding_chars != padding_len) return error.InvalidPadding; } - return dest_idx; } }; |