lib/wayland/src/runtime/message.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const sys = @import("sys");
3 const wayland = @import("../root.zig");
4
5 pub const RoutedView = struct {
6 object_id: u32,
7 interface: *const wayland.protocol.schema.Interface,
8 version: u32,
9 metadata: *const wayland.protocol.schema.Message,
10 payload: []const u8,
11 descriptors: []sys.fd.Descriptor,
12
13 pub fn borrowedDecoder(
14 self: *const RoutedView,
15 ) wayland.protocol.value.DecodeError!wayland.protocol.value.Decoder {
16 return .init(self.metadata, self.payload, self.descriptors);
17 }
18
19 pub fn takeDescriptor(
20 self: *RoutedView,
21 index: usize,
22 ) error{ InvalidIndex, DescriptorAlreadyTaken }!sys.fd.Descriptor {
23 if (index >= self.descriptors.len) return error.InvalidIndex;
24 const descriptor = self.descriptors[index];
25 if (descriptor < 0) return error.DescriptorAlreadyTaken;
26 self.descriptors[index] = -1;
27 return descriptor;
28 }
29 };
30
31 test "routed messages transfer descriptor ownership explicitly" {
32 const metadata = &wayland.protocol.core.wl_keyboard.events.keymap;
33 const pipe = try sys.fd.pipeWithOptions(.{ .close_on_exec = true });
34 defer sys.fd.close(pipe[0]);
35
36 const payload = [_]u8{ 1, 0, 0, 0, 8, 0, 0, 0 };
37 var descriptors = [_]sys.fd.Descriptor{pipe[1]};
38 var routed: RoutedView = .{
39 .object_id = 2,
40 .interface = &wayland.protocol.core.wl_keyboard.metadata,
41 .version = 1,
42 .metadata = metadata,
43 .payload = &payload,
44 .descriptors = &descriptors,
45 };
46
47 var decoder = try routed.borrowedDecoder();
48 try std.testing.expectEqual(@as(u32, 1), try decoder.unsigned());
49 try std.testing.expectEqual(pipe[1], try decoder.descriptor());
50 try std.testing.expectEqual(@as(u32, 8), try decoder.unsigned());
51 try decoder.finish();
52 const taken = try routed.takeDescriptor(0);
53 defer sys.fd.close(taken);
54 try std.testing.expectError(error.DescriptorAlreadyTaken, routed.takeDescriptor(0));
55 try std.testing.expectEqual(@as(usize, 1), try sys.fd.write(taken, "x"));
56 var byte: [1]u8 = undefined;
57 try std.testing.expectEqual(@as(usize, 1), try sys.fd.read(pipe[0], &byte));
58 try std.testing.expectEqual(@as(u8, 'x'), byte[0]);
59 }