| ... | @@ -5,6 +5,7 @@ const assert = std.debug.assert; | ... | @@ -5,6 +5,7 @@ const assert = std.debug.assert; |
| 5 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 6 | const testing = std.testing; | 6 | const testing = std.testing; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| | 8 | const window = mem.window; |
| 8 | | 9 | |
| 9 | pub const Error = error{ | 10 | pub const Error = error{ |
| 10 | InvalidCharacter, | 11 | InvalidCharacter, |
| ... | @@ -98,6 +99,32 @@ pub const Base64Encoder = struct { | ... | @@ -98,6 +99,32 @@ pub const Base64Encoder = struct { |
| 98 | } | 99 | } |
| 99 | } | 100 | } |
| 100 | | 101 | |
| | 102 | // dest must be compatible with std.io.Writer's writeAll interface |
| | 103 | pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void { |
| | 104 | var chunker = window(u8, source, 3, 3); |
| | 105 | while (chunker.next()) |chunk| { |
| | 106 | var temp: [5]u8 = undefined; |
| | 107 | const s = encoder.encode(&temp, chunk); |
| | 108 | try dest.writeAll(s); |
| | 109 | } |
| | 110 | } |
| | 111 | |
| | 112 | // destWriter must be compatible with std.io.Writer's writeAll interface |
| | 113 | // sourceReader must be compatible with std.io.Reader's read interface |
| | 114 | pub fn encodeFromReaderToWriter(encoder: *const Base64Encoder, destWriter: anytype, sourceReader: anytype) !void { |
| | 115 | while (true) { |
| | 116 | var tempSource: [3]u8 = undefined; |
| | 117 | const bytesRead = try sourceReader.read(&tempSource); |
| | 118 | if (bytesRead == 0) { |
| | 119 | break; |
| | 120 | } |
| | 121 | |
| | 122 | var temp: [5]u8 = undefined; |
| | 123 | const s = encoder.encode(&temp, tempSource[0..bytesRead]); |
| | 124 | try destWriter.writeAll(s); |
| | 125 | } |
| | 126 | } |
| | 127 | |
| 101 | /// dest.len must at least be what you get from ::calcSize. | 128 | /// dest.len must at least be what you get from ::calcSize. |
| 102 | pub fn encode(encoder: *const Base64Encoder, dest: []u8, source: []const u8) []const u8 { | 129 | pub fn encode(encoder: *const Base64Encoder, dest: []u8, source: []const u8) []const u8 { |
| 103 | const out_len = encoder.calcSize(source.len); | 130 | const out_len = encoder.calcSize(source.len); |
| ... | @@ -477,9 +504,21 @@ fn testBase64UrlSafeNoPad() !void { | ... | @@ -477,9 +504,21 @@ fn testBase64UrlSafeNoPad() !void { |
| 477 | fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void { | 504 | fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void { |
| 478 | // Base64Encoder | 505 | // Base64Encoder |
| 479 | { | 506 | { |
| | 507 | // raw encode |
| 480 | var buffer: [0x100]u8 = undefined; | 508 | var buffer: [0x100]u8 = undefined; |
| 481 | const encoded = codecs.Encoder.encode(&buffer, expected_decoded); | 509 | const encoded = codecs.Encoder.encode(&buffer, expected_decoded); |
| 482 | try testing.expectEqualSlices(u8, expected_encoded, encoded); | 510 | try testing.expectEqualSlices(u8, expected_encoded, encoded); |
| | 511 | |
| | 512 | // stream encode |
| | 513 | var list = try std.BoundedArray(u8, 0x100).init(0); |
| | 514 | try codecs.Encoder.encodeWriter(list.writer(), expected_decoded); |
| | 515 | try testing.expectEqualSlices(u8, expected_encoded, list.slice()); |
| | 516 | |
| | 517 | // reader to writer encode |
| | 518 | var stream = std.io.fixedBufferStream(expected_decoded); |
| | 519 | list = try std.BoundedArray(u8, 0x100).init(0); |
| | 520 | try codecs.Encoder.encodeFromReaderToWriter(list.writer(), stream.reader()); |
| | 521 | try testing.expectEqualSlices(u8, expected_encoded, list.slice()); |
| 483 | } | 522 | } |
| 484 | | 523 | |
| 485 | // Base64Decoder | 524 | // Base64Decoder |