| ... | @@ -21,7 +21,6 @@ pub const Codecs = struct { | ... | @@ -21,7 +21,6 @@ pub const Codecs = struct { |
| 21 | decoderWithIgnore: fn (ignore: []const u8) Base64DecoderWithIgnore, | 21 | decoderWithIgnore: fn (ignore: []const u8) Base64DecoderWithIgnore, |
| 22 | Encoder: Base64Encoder, | 22 | Encoder: Base64Encoder, |
| 23 | Decoder: Base64Decoder, | 23 | Decoder: Base64Decoder, |
| 24 | DecoderUnsafe: Base64DecoderUnsafe, | | |
| 25 | }; | 24 | }; |
| 26 | | 25 | |
| 27 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".*; | 26 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".*; |
| ... | @@ -36,7 +35,6 @@ pub const standard = Codecs{ | ... | @@ -36,7 +35,6 @@ pub const standard = Codecs{ |
| 36 | .decoderWithIgnore = standardBase64DecoderWithIgnore, | 35 | .decoderWithIgnore = standardBase64DecoderWithIgnore, |
| 37 | .Encoder = Base64Encoder.init(standard_alphabet_chars, '='), | 36 | .Encoder = Base64Encoder.init(standard_alphabet_chars, '='), |
| 38 | .Decoder = Base64Decoder.init(standard_alphabet_chars, '='), | 37 | .Decoder = Base64Decoder.init(standard_alphabet_chars, '='), |
| 39 | .DecoderUnsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, '='), | | |
| 40 | }; | 38 | }; |
| 41 | | 39 | |
| 42 | /// Standard Base64 codecs, without padding | 40 | /// Standard Base64 codecs, without padding |
| ... | @@ -46,7 +44,6 @@ pub const standard_no_pad = Codecs{ | ... | @@ -46,7 +44,6 @@ pub const standard_no_pad = Codecs{ |
| 46 | .decoderWithIgnore = standardBase64DecoderWithIgnore, | 44 | .decoderWithIgnore = standardBase64DecoderWithIgnore, |
| 47 | .Encoder = Base64Encoder.init(standard_alphabet_chars, null), | 45 | .Encoder = Base64Encoder.init(standard_alphabet_chars, null), |
| 48 | .Decoder = Base64Decoder.init(standard_alphabet_chars, null), | 46 | .Decoder = Base64Decoder.init(standard_alphabet_chars, null), |
| 49 | .DecoderUnsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, null), | | |
| 50 | }; | 47 | }; |
| 51 | | 48 | |
| 52 | pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; | 49 | pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; |
| ... | @@ -61,7 +58,6 @@ pub const url_safe = Codecs{ | ... | @@ -61,7 +58,6 @@ pub const url_safe = Codecs{ |
| 61 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, | 58 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, |
| 62 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, '='), | 59 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, '='), |
| 63 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, '='), | 60 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, '='), |
| 64 | .DecoderUnsafe = Base64DecoderUnsafe.init(url_safe_alphabet_chars, '='), | | |
| 65 | }; | 61 | }; |
| 66 | | 62 | |
| 67 | /// URL-safe Base64 codecs, without padding | 63 | /// URL-safe Base64 codecs, without padding |
| ... | @@ -71,7 +67,6 @@ pub const url_safe_no_pad = Codecs{ | ... | @@ -71,7 +67,6 @@ pub const url_safe_no_pad = Codecs{ |
| 71 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, | 67 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, |
| 72 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, null), | 68 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, null), |
| 73 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, null), | 69 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, null), |
| 74 | .DecoderUnsafe = Base64DecoderUnsafe.init(url_safe_alphabet_chars, null), | | |
| 75 | }; | 70 | }; |
| 76 | | 71 | |
| 77 | // Backwards compatibility | 72 | // Backwards compatibility |
| ... | @@ -82,8 +77,6 @@ pub const standard_pad_char = standard.pad_char; | ... | @@ -82,8 +77,6 @@ pub const standard_pad_char = standard.pad_char; |
| 82 | pub const standard_encoder = standard.Encoder; | 77 | pub const standard_encoder = standard.Encoder; |
| 83 | /// Deprecated - Use `standard.Decoder` | 78 | /// Deprecated - Use `standard.Decoder` |
| 84 | pub const standard_decoder = standard.Decoder; | 79 | pub const standard_decoder = standard.Decoder; |
| 85 | /// Deprecated - Use `standard.DecoderUnsafe` | | |
| 86 | pub const standard_decoder_unsafe = standard.DecoderUnsafe; | | |
| 87 | | 80 | |
| 88 | pub const Base64Encoder = struct { | 81 | pub const Base64Encoder = struct { |
| 89 | alphabet_chars: [64]u8, | 82 | alphabet_chars: [64]u8, |
| ... | @@ -323,75 +316,6 @@ pub const Base64DecoderWithIgnore = struct { | ... | @@ -323,75 +316,6 @@ pub const Base64DecoderWithIgnore = struct { |
| 323 | } | 316 | } |
| 324 | }; | 317 | }; |
| 325 | | 318 | |
| 326 | pub const Base64DecoderUnsafe = struct { | | |
| 327 | /// e.g. 'A' => 0. | | |
| 328 | /// undefined for any value not in the 64 alphabet chars. | | |
| 329 | char_to_index: [256]u8, | | |
| 330 | pad_char: ?u8, | | |
| 331 | | | |
| 332 | pub fn init(alphabet_chars: [64]u8, pad_char: ?u8) Base64DecoderUnsafe { | | |
| 333 | var result = Base64DecoderUnsafe{ | | |
| 334 | .char_to_index = undefined, | | |
| 335 | .pad_char = pad_char, | | |
| 336 | }; | | |
| 337 | for (alphabet_chars) |c, i| { | | |
| 338 | assert(pad_char == null or c != pad_char.?); | | |
| 339 | result.char_to_index[c] = @intCast(u8, i); | | |
| 340 | } | | |
| 341 | return result; | | |
| 342 | } | | |
| 343 | | | |
| 344 | /// Return the exact decoded size for a slice. | | |
| 345 | /// `InvalidPadding` is returned if the input length is not valid. | | |
| 346 | pub fn calcSizeForSlice(decoder: *const Base64DecoderUnsafe, source: []const u8) Error!usize { | | |
| 347 | const safe_decoder = Base64Decoder{ .char_to_index = undefined, .pad_char = decoder.pad_char }; | | |
| 348 | return safe_decoder.calcSizeForSlice(source); | | |
| 349 | } | | |
| 350 | | | |
| 351 | /// dest.len must be what you get from ::calcDecodedSizeExactUnsafe. | | |
| 352 | /// invalid characters or padding will result in undefined values. | | |
| 353 | pub fn decode(decoder: *const Base64DecoderUnsafe, dest: []u8, source: []const u8) void { | | |
| 354 | assert(dest.len == decoder.calcSizeForSlice(source) catch unreachable); | | |
| 355 | | | |
| 356 | var src_index: usize = 0; | | |
| 357 | var dest_index: usize = 0; | | |
| 358 | var in_buf_len: usize = source.len; | | |
| 359 | | | |
| 360 | if (decoder.pad_char) |pad_char| { | | |
| 361 | while (in_buf_len > 0 and source[in_buf_len - 1] == pad_char) { | | |
| 362 | in_buf_len -= 1; | | |
| 363 | } | | |
| 364 | } | | |
| 365 | | | |
| 366 | while (in_buf_len > 4) { | | |
| 367 | dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4; | | |
| 368 | dest_index += 1; | | |
| 369 | | | |
| 370 | dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2; | | |
| 371 | dest_index += 1; | | |
| 372 | | | |
| 373 | dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]]; | | |
| 374 | dest_index += 1; | | |
| 375 | | | |
| 376 | src_index += 4; | | |
| 377 | in_buf_len -= 4; | | |
| 378 | } | | |
| 379 | | | |
| 380 | if (in_buf_len > 1) { | | |
| 381 | dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4; | | |
| 382 | dest_index += 1; | | |
| 383 | } | | |
| 384 | if (in_buf_len > 2) { | | |
| 385 | dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2; | | |
| 386 | dest_index += 1; | | |
| 387 | } | | |
| 388 | if (in_buf_len > 3) { | | |
| 389 | dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]]; | | |
| 390 | dest_index += 1; | | |
| 391 | } | | |
| 392 | } | | |
| 393 | }; | | |
| 394 | | | |
| 395 | test "base64" { | 319 | test "base64" { |
| 396 | @setEvalBranchQuota(8000); | 320 | @setEvalBranchQuota(8000); |
| 397 | testBase64() catch unreachable; | 321 | testBase64() catch unreachable; |
| ... | @@ -500,14 +424,6 @@ fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: [ | ... | @@ -500,14 +424,6 @@ fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: [ |
| 500 | testing.expect(written <= decoded.len); | 424 | testing.expect(written <= decoded.len); |
| 501 | testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]); | 425 | testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]); |
| 502 | } | 426 | } |
| 503 | | | |
| 504 | // Base64DecoderUnsafe | | |
| 505 | { | | |
| 506 | var buffer: [0x100]u8 = undefined; | | |
| 507 | var decoded = buffer[0..try codecs.DecoderUnsafe.calcSizeForSlice(expected_encoded)]; | | |
| 508 | codecs.DecoderUnsafe.decode(decoded, expected_encoded); | | |
| 509 | testing.expectEqualSlices(u8, expected_decoded, decoded); | | |
| 510 | } | | |
| 511 | } | 427 | } |
| 512 | | 428 | |
| 513 | fn testDecodeIgnoreSpace(codecs: Codecs, expected_decoded: []const u8, encoded: []const u8) !void { | 429 | fn testDecodeIgnoreSpace(codecs: Codecs, expected_decoded: []const u8, encoded: []const u8) !void { |