diff --git a/lib/std/base64.zig b/lib/std/base64.zig index 2627480295..243f206445 100644 --- a/lib/std/base64.zig +++ b/lib/std/base64.zig @@ -5,6 +5,7 @@ const assert = std.debug.assert; const builtin = @import("builtin"); const testing = std.testing; const mem = std.mem; +const window = mem.window; pub const Error = error{ InvalidCharacter, @@ -98,6 +99,32 @@ pub const Base64Encoder = struct { } } + // dest must be compatible with std.io.Writer's writeAll interface + pub fn encodeWriter(encoder: *const Base64Encoder, dest: anytype, source: []const u8) !void { + var chunker = window(u8, source, 3, 3); + while (chunker.next()) |chunk| { + var temp: [5]u8 = undefined; + const s = encoder.encode(&temp, chunk); + try dest.writeAll(s); + } + } + + // destWriter must be compatible with std.io.Writer's writeAll interface + // sourceReader must be compatible with std.io.Reader's read interface + pub fn encodeFromReaderToWriter(encoder: *const Base64Encoder, destWriter: anytype, sourceReader: anytype) !void { + while (true) { + var tempSource: [3]u8 = undefined; + const bytesRead = try sourceReader.read(&tempSource); + if (bytesRead == 0) { + break; + } + + var temp: [5]u8 = undefined; + const s = encoder.encode(&temp, tempSource[0..bytesRead]); + try destWriter.writeAll(s); + } + } + /// dest.len must at least be what you get from ::calcSize. pub fn encode(encoder: *const Base64Encoder, dest: []u8, source: []const u8) []const u8 { const out_len = encoder.calcSize(source.len); @@ -477,9 +504,21 @@ fn testBase64UrlSafeNoPad() !void { fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void { // Base64Encoder { + // raw encode var buffer: [0x100]u8 = undefined; const encoded = codecs.Encoder.encode(&buffer, expected_decoded); try testing.expectEqualSlices(u8, expected_encoded, encoded); + + // stream encode + var list = try std.BoundedArray(u8, 0x100).init(0); + try codecs.Encoder.encodeWriter(list.writer(), expected_decoded); + try testing.expectEqualSlices(u8, expected_encoded, list.slice()); + + // reader to writer encode + var stream = std.io.fixedBufferStream(expected_decoded); + list = try std.BoundedArray(u8, 0x100).init(0); + try codecs.Encoder.encodeFromReaderToWriter(list.writer(), stream.reader()); + try testing.expectEqualSlices(u8, expected_encoded, list.slice()); } // Base64Decoder