home
tpb

repository View

tests(OSC52): Added base64 encoding test cases

change ID
uqttuptknuzknrxvqsxpvxxsozpvkmqp
git commit
47f2491ae0688637d82900dfe8d92b8b4e774e8e
author
Grace Yoder <grace_yoder@outlook.com> - 2026-06-24T17:48:16-06:00
committer
Grace Yoder <grace_yoder@outlook.com> - 2026-06-25T16:42:38-06:00
parents
tvtsvtzvysvm
refs
signature
Present (not validated)
tests(OSC52): Added base64 encoding test cases

tree

type name size
file .crow/build.yml 2096 bytes
file .crow/release.yml 566 bytes
file .gitignore 354 bytes
file LICENSE 1073 bytes
file README.md 632 bytes
file build.zig 680 bytes
file build.zig.zon 247 bytes
file src/Clip/OSC52.zig 4611 bytes
file src/Clip.zig 45 bytes
file src/main.zig 1370 bytes

diff

src/Clip/OSC52.zig

modified (file → file)

--- a/src/Clip/OSC52.zig
+++ b/src/Clip/OSC52.zig
@@ -13,7 +13,7 @@
 leftover_bytes: [3]u8,
 leftover_count: u8,
 
-const base64encoder = std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, null);
+const base64encoder = std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, '=');
 
 pub fn init(alloc: std.mem.Allocator, io: Io, buf_size: usize) !OSC52 {
     return .{
@@ -25,31 +25,34 @@
     };
 }
 
-pub fn writeCopyBuffer(self: *OSC52, buf: []u8) !void {
+pub fn free(self: *OSC52) void {
+    self.base64buffer.clearAndFree(self.alloc);
+}
+
+pub fn writeCopyBuffer(self: *OSC52, buf: []const u8) anyerror!void {
     if (buf.len == 0) return;
 
     // Start of buffer after dealing with leftover bytes
     const buf_idx = 3 - self.leftover_count;
 
-    if (buf.len + self.leftover_count < 3) {
-        const len = buf.len + self.leftover_count;
-        @memcpy(self.leftover_bytes[self.leftover_count..len], buf[0..buf.len]);
-        self.leftover_count = @intCast(len);
+    // When we dont fill the leftover buffer, just copy data
+    if (buf_idx > buf.len) {
+        const end = self.leftover_count + buf.len;
+        @memcpy(self.leftover_bytes[self.leftover_count..end], buf[0..buf.len]);
+        self.leftover_count = @intCast(end);
         return;
     }
 
-    if (self.leftover_count != 0) {
-        @memcpy(self.leftover_bytes[self.leftover_count..3], buf[0..buf_idx]);
-        var temp: [5]u8 = undefined;
-        const s = OSC52.base64encoder.encode(&temp, &self.leftover_bytes);
-        try self.base64buffer.appendSlice(self.alloc, s);
-    }
+    @memcpy(self.leftover_bytes[self.leftover_count..3], buf[0..buf_idx]);
+    var temp: [5]u8 = undefined;
+    var s = OSC52.base64encoder.encode(&temp, &self.leftover_bytes);
+    try self.base64buffer.appendSlice(self.alloc, s);
 
     const chunkable_length = buf.len - ((buf.len - buf_idx) % 3);
-    var chunker = std.mem.window(u8, buf[0..chunkable_length], 3, 3);
+    var chunker = std.mem.window(u8, buf[buf_idx..chunkable_length], 3, 3);
     while (chunker.next()) |chunk| {
-        var temp: [5]u8 = undefined;
-        const s = OSC52.base64encoder.encode(&temp, chunk);
+        // var temp: [5]u8 = undefined;
+        s = OSC52.base64encoder.encode(&temp, chunk);
         try self.base64buffer.appendSlice(self.alloc, s);
     }
 
@@ -59,7 +62,14 @@
     }
 }
 
-pub fn writePasteboard(self: *OSC52) !void {
+pub fn encodeRemaining(self: *OSC52) anyerror!void {
+    var temp: [5]u8 = undefined;
+    const s = OSC52.base64encoder.encode(&temp, self.leftover_bytes[0..self.leftover_count]);
+    try self.base64buffer.appendSlice(self.alloc, s);
+}
+
+pub fn writePasteboard(self: *OSC52) anyerror!void {
+    try self.encodeRemaining();
 
     // https://ghostty.org/docs/vt/osc/52
     const osc_header = &[_]u8{
@@ -76,14 +86,51 @@
         0x5c, // '\'
     };
 
-    // Write leftover bytes
-    var temp: [5]u8 = undefined;
-    const s = OSC52.base64encoder.encode(&temp, self.leftover_bytes[0..self.leftover_count]);
-    try self.base64buffer.appendSlice(self.alloc, s);
-
     // Write data to stdout
     const stdout = Io.File.stdout();
     try stdout.writeStreamingAll(self.io, osc_header);
     try stdout.writeStreamingAll(self.io, self.base64buffer.items);
     try stdout.writeStreamingAll(self.io, osc_footer);
 }
+
+test "basic base64 encode" {
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    defer osc.free();
+    try osc.writeCopyBuffer("part1");
+    try osc.encodeRemaining();
+    try std.testing.expectEqualSlices(u8, "cGFydDE=", osc.base64buffer.items);
+}
+
+test "multi part base64 encode" {
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    defer osc.free();
+    try osc.writeCopyBuffer("part1");
+    try osc.writeCopyBuffer("part2");
+    try osc.encodeRemaining();
+    try std.testing.expectEqualSlices(u8, "cGFydDFwYXJ0Mg==", osc.base64buffer.items);
+}
+
+test "tiny buffers base64 encode" {
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    defer osc.free();
+    try osc.writeCopyBuffer("part1");
+    try osc.writeCopyBuffer("part2");
+    try osc.writeCopyBuffer("1");
+    try osc.writeCopyBuffer("2");
+    try osc.writeCopyBuffer("3");
+    try osc.writeCopyBuffer("45");
+    try osc.writeCopyBuffer("6");
+    try osc.writeCopyBuffer("78");
+    try osc.writeCopyBuffer("90fin");
+    try osc.encodeRemaining();
+    try std.testing.expectEqualSlices(u8, "cGFydDFwYXJ0MjEyMzQ1Njc4OTBmaW4=", osc.base64buffer.items);
+}
+
+test "big buffers base64 encode" {
+    var osc = try OSC52.init(std.testing.allocator, std.testing.io, 1024);
+    defer osc.free();
+    try osc.writeCopyBuffer("part1part1part1part1part1part1part1part1part1|");
+    try osc.writeCopyBuffer("part2part2part2part2part2part2part2part2part2");
+    try osc.encodeRemaining();
+    try std.testing.expectEqualSlices(u8, "cGFydDFwYXJ0MXBhcnQxcGFydDFwYXJ0MXBhcnQxcGFydDFwYXJ0MXBhcnQxfHBhcnQycGFydDJwYXJ0MnBhcnQycGFydDJwYXJ0MnBhcnQycGFydDJwYXJ0Mg==", osc.base64buffer.items);
+}

src/main.zig

modified (file → file)

--- a/src/main.zig
+++ b/src/main.zig
@@ -38,3 +38,7 @@
 
     std.debug.print("\x1b[0;32mCopied To Pasteboard!\x1b[0m\n", .{});
 }
+
+test {
+    _ = @import("Clip.zig");
+}