From a5a977be9f81b85efd74ca2e5b4cd5e5733f0489 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 21 Aug 2023 14:52:46 -0700 Subject: [PATCH] terminal/kitty-gfx: file medium --- src/terminal/kitty/graphics_image.zig | 83 +++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/src/terminal/kitty/graphics_image.zig b/src/terminal/kitty/graphics_image.zig index d415b8f77..89c01d3ae 100644 --- a/src/terminal/kitty/graphics_image.zig +++ b/src/terminal/kitty/graphics_image.zig @@ -83,33 +83,56 @@ pub const LoadingImage = struct { // Depending on the medium, load the data from the path. switch (t.medium) { .direct => unreachable, // handled above - - .temporary_file => try result.readTemporaryFile(alloc, t, path), - - else => { - std.log.warn("unimplemented medium={}", .{t.medium}); - return error.UnsupportedMedium; - }, + .file => try result.readFile(.file, alloc, t, path), + .temporary_file => try result.readFile(.temporary_file, alloc, t, path), + .shared_memory => try result.readSharedMemory(alloc, t, path), } return result; } + /// Reads the data from a shared memory segment. + fn readSharedMemory( + self: *LoadingImage, + alloc: Allocator, + t: command.Transmission, + path: []const u8, + ) !void { + // We require libc for this for shm_open + if (comptime !builtin.link_libc) return error.UnsupportedMedium; + + // Todo: support shared memory + _ = self; + _ = alloc; + _ = t; + _ = path; + return error.UnsupportedMedium; + } + /// Reads the data from a temporary file and returns it. This allocates /// and does not free any of the data, so the caller must free it. /// /// This will also delete the temporary file if it is in a safe location. - fn readTemporaryFile( + fn readFile( self: *LoadingImage, + comptime medium: command.Transmission.Medium, alloc: Allocator, t: command.Transmission, path: []const u8, ) !void { - if (!isPathInTempDir(path)) return error.TemporaryFileNotInTempDir; + switch (medium) { + .file, .temporary_file => {}, + else => @compileError("readFile only supports file and temporary_file"), + } - // Delete the temporary file - defer std.os.unlink(path) catch |err| { - log.warn("failed to delete temporary file: {}", .{err}); + // Temporary file logic + if (medium == .temporary_file) { + if (!isPathInTempDir(path)) return error.TemporaryFileNotInTempDir; + } + defer if (medium == .temporary_file) { + std.os.unlink(path) catch |err| { + log.warn("failed to delete temporary file: {}", .{err}); + }; }; var file = std.fs.cwd().openFile(path, .{}) catch |err| { @@ -527,3 +550,39 @@ test "image load: rgb, not compressed, temporary file" { // Temporary file should be gone try testing.expectError(error.FileNotFound, tmp_dir.dir.access(path, .{})); } + +test "image load: rgb, not compressed, regular file" { + const testing = std.testing; + const alloc = testing.allocator; + + var tmp_dir = try internal_os.TempDir.init(); + defer tmp_dir.deinit(); + const data = try testB64Decode( + alloc, + @embedFile("testdata/image-rgb-none-20x15-2147483647.data"), + ); + defer alloc.free(data); + try tmp_dir.dir.writeFile("image.data", data); + + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + const path = try tmp_dir.dir.realpath("image.data", &buf); + + var cmd: command.Command = .{ + .control = .{ .transmit = .{ + .format = .rgb, + .medium = .file, + .compression = .none, + .width = 20, + .height = 15, + .image_id = 31, + } }, + .data = try testB64(alloc, path), + }; + defer cmd.deinit(alloc); + var loading = try LoadingImage.init(alloc, &cmd); + defer loading.deinit(alloc); + var img = try loading.complete(alloc); + defer img.deinit(alloc); + try testing.expect(img.compression == .none); + try tmp_dir.dir.access(path, .{}); +}