aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/datastruct/message_data.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/datastruct/message_data.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/datastruct/message_data.zig')
-rw-r--r--vendor/libghostty-vt/src/datastruct/message_data.zig124
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/datastruct/message_data.zig b/vendor/libghostty-vt/src/datastruct/message_data.zig
new file mode 100644
index 00000000..3e5cdae6
--- /dev/null
+++ b/vendor/libghostty-vt/src/datastruct/message_data.zig
@@ -0,0 +1,124 @@
+const std = @import("std");
+const assert = @import("../quirks.zig").inlineAssert;
+const Allocator = std.mem.Allocator;
+
+/// Creates a union that can be used to accommodate data that fit within an array,
+/// are a stable pointer, or require deallocation. This is helpful for thread
+/// messaging utilities.
+pub fn MessageData(comptime Elem: type, comptime small_size: comptime_int) type {
+ return union(enum) {
+ pub const Self = @This();
+
+ pub const Small = struct {
+ pub const Max = small_size;
+ pub const Array = [Max]Elem;
+ pub const Len = std.math.IntFittingRange(0, small_size);
+ data: Array = undefined,
+ len: Len = 0,
+ };
+
+ pub const Alloc = struct {
+ alloc: Allocator,
+ data: []Elem,
+ };
+
+ pub const Stable = []const Elem;
+
+ /// A small write where the data fits into this union size.
+ small: Small,
+
+ /// A stable pointer so we can just pass the slice directly through.
+ /// This is useful i.e. for const data.
+ stable: Stable,
+
+ /// Allocated and must be freed with the provided allocator. This
+ /// should be rarely used.
+ alloc: Alloc,
+
+ /// Initializes the union for a given data type. This will
+ /// attempt to fit into a small value if possible, otherwise
+ /// will allocate and put into alloc.
+ ///
+ /// This can't and will never detect stable pointers.
+ pub fn init(alloc: Allocator, data: anytype) !Self {
+ switch (@typeInfo(@TypeOf(data))) {
+ .pointer => |info| {
+ assert(info.size == .slice);
+ assert(info.child == Elem);
+
+ // If it fits in our small request, do that.
+ if (data.len <= Small.Max) {
+ var buf: Small.Array = undefined;
+ @memcpy(buf[0..data.len], data);
+ return Self{
+ .small = .{
+ .data = buf,
+ .len = @intCast(data.len),
+ },
+ };
+ }
+
+ // Otherwise, allocate
+ const buf = try alloc.dupe(Elem, data);
+ errdefer alloc.free(buf);
+ return Self{
+ .alloc = .{
+ .alloc = alloc,
+ .data = buf,
+ },
+ };
+ },
+
+ else => unreachable,
+ }
+ }
+
+ pub fn deinit(self: Self) void {
+ switch (self) {
+ .small, .stable => {},
+ .alloc => |v| v.alloc.free(v.data),
+ }
+ }
+
+ /// Returns a const slice of the data pointed to by this request.
+ pub fn slice(self: *const Self) []const Elem {
+ return switch (self.*) {
+ .small => |*v| v.data[0..v.len],
+ .stable => |v| v,
+ .alloc => |v| v.data,
+ };
+ }
+ };
+}
+
+test "MessageData init small" {
+ const testing = std.testing;
+ const alloc = testing.allocator;
+
+ const Data = MessageData(u8, 10);
+ const input = "hello!";
+ const io = try Data.init(alloc, @as([]const u8, input));
+ try testing.expect(io == .small);
+}
+
+test "MessageData init alloc" {
+ const testing = std.testing;
+ const alloc = testing.allocator;
+
+ const Data = MessageData(u8, 10);
+ const input = "hello! " ** 100;
+ const io = try Data.init(alloc, @as([]const u8, input));
+ try testing.expect(io == .alloc);
+ io.alloc.alloc.free(io.alloc.data);
+}
+
+test "MessageData small fits non-u8 sized data" {
+ const testing = std.testing;
+ const alloc = testing.allocator;
+
+ const len = 500;
+ const Data = MessageData(u8, len);
+ const input: []const u8 = "X" ** len;
+ const io = try Data.init(alloc, input);
+ try testing.expect(io == .small);
+}