| ... | ... | @@ -21,7 +21,6 @@ pub const Codecs = struct { |
| 21 | 21 | decoderWithIgnore: fn (ignore: []const u8) Base64DecoderWithIgnore, |
| 22 | 22 | Encoder: Base64Encoder, |
| 23 | 23 | Decoder: Base64Decoder, |
| 24 | | DecoderUnsafe: Base64DecoderUnsafe, |
| 25 | 24 | }; |
| 26 | 25 | |
| 27 | 26 | pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".*; |
| ... | ... | @@ -36,7 +35,6 @@ pub const standard = Codecs{ |
| 36 | 35 | .decoderWithIgnore = standardBase64DecoderWithIgnore, |
| 37 | 36 | .Encoder = Base64Encoder.init(standard_alphabet_chars, '='), |
| 38 | 37 | .Decoder = Base64Decoder.init(standard_alphabet_chars, '='), |
| 39 | | .DecoderUnsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, '='), |
| 40 | 38 | }; |
| 41 | 39 | |
| 42 | 40 | /// Standard Base64 codecs, without padding |
| ... | ... | @@ -46,7 +44,6 @@ pub const standard_no_pad = Codecs{ |
| 46 | 44 | .decoderWithIgnore = standardBase64DecoderWithIgnore, |
| 47 | 45 | .Encoder = Base64Encoder.init(standard_alphabet_chars, null), |
| 48 | 46 | .Decoder = Base64Decoder.init(standard_alphabet_chars, null), |
| 49 | | .DecoderUnsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, null), |
| 50 | 47 | }; |
| 51 | 48 | |
| 52 | 49 | pub const url_safe_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; |
| ... | ... | @@ -61,7 +58,6 @@ pub const url_safe = Codecs{ |
| 61 | 58 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, |
| 62 | 59 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, '='), |
| 63 | 60 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, '='), |
| 64 | | .DecoderUnsafe = Base64DecoderUnsafe.init(url_safe_alphabet_chars, '='), |
| 65 | 61 | }; |
| 66 | 62 | |
| 67 | 63 | /// URL-safe Base64 codecs, without padding |
| ... | ... | @@ -71,7 +67,6 @@ pub const url_safe_no_pad = Codecs{ |
| 71 | 67 | .decoderWithIgnore = urlSafeBase64DecoderWithIgnore, |
| 72 | 68 | .Encoder = Base64Encoder.init(url_safe_alphabet_chars, null), |
| 73 | 69 | .Decoder = Base64Decoder.init(url_safe_alphabet_chars, null), |
| 74 | | .DecoderUnsafe = Base64DecoderUnsafe.init(url_safe_alphabet_chars, null), |
| 75 | 70 | }; |
| 76 | 71 | |
| 77 | 72 | // Backwards compatibility |
| ... | ... | @@ -82,8 +77,6 @@ pub const standard_pad_char = standard.pad_char; |
| 82 | 77 | pub const standard_encoder = standard.Encoder; |
| 83 | 78 | /// Deprecated - Use `standard.Decoder` |
| 84 | 79 | pub const standard_decoder = standard.Decoder; |
| 85 | | /// Deprecated - Use `standard.DecoderUnsafe` |
| 86 | | pub const standard_decoder_unsafe = standard.DecoderUnsafe; |
| 87 | 80 | |
| 88 | 81 | pub const Base64Encoder = struct { |
| 89 | 82 | alphabet_chars: [64]u8, |
| ... | ... | @@ -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 | 319 | test "base64" { |
| 396 | 320 | @setEvalBranchQuota(8000); |
| 397 | 321 | testBase64() catch unreachable; |
| ... | ... | @@ -500,14 +424,6 @@ fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: [ |
| 500 | 424 | testing.expect(written <= decoded.len); |
| 501 | 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 | 429 | fn testDecodeIgnoreSpace(codecs: Codecs, expected_decoded: []const u8, encoded: []const u8) !void { |