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 }