authorgravatar for siragentprovocateurarwalk@gmail.comArwalk <siragentprovocateurarwalk@gmail.com> 2024-09-04 10:10:12+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-09-04 08:10:12+00:00
logf87dd43c1285d38d7a0f3092f6487bf1e1f4faa6
treee809628219f6608ac9cfe0708ae96f919c01006f
parente5ee9c1e43d74354f12fc6cf76f39f7a607558ca
signaturebadge-check Signed by PGP key B5690EEEBB952194

stdlib : base64 encode to writer (#20961)


1 files changed, 39 insertions(+), 0 deletions(-)

lib/std/base64.zig+39
...@@ -5,6 +5,7 @@ const assert = std.debug.assert;...@@ -5,6 +5,7 @@ const assert = std.debug.assert;
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const testing = std.testing;6const testing = std.testing;
7const mem = std.mem;7const mem = std.mem;
8const window = mem.window;
89
9pub const Error = error{10pub 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 }
100101
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 {
477fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void {504fn testAllApis(codecs: Codecs, expected_decoded: []const u8, expected_encoded: []const u8) !void {
478 // Base64Encoder505 // 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 }
484523
485 // Base64Decoder524 // Base64Decoder