lib/wayland/src/protocol/bootstrap/display.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const protocol = @import("../root.zig");
 2 
 3 const core = protocol.core.wl_display;
 4 
 5 pub const Sync = struct {
 6     callback: protocol.value.NewId,
 7 
 8     pub fn encode(self: Sync, encoder: *protocol.value.Encoder) !protocol.value.Encoded {
 9         encoder.reset();
10         errdefer encoder.reset();
11         try encoder.newId(self.callback);
12         return encoder.finish(&core.requests.sync);
13     }
14 };
15 
16 pub const GetRegistry = struct {
17     registry: protocol.value.NewId,
18 
19     pub fn encode(self: GetRegistry, encoder: *protocol.value.Encoder) !protocol.value.Encoded {
20         encoder.reset();
21         errdefer encoder.reset();
22         try encoder.newId(self.registry);
23         return encoder.finish(&core.requests.get_registry);
24     }
25 };
26 
27 pub const Fatal = struct {
28     object_id: protocol.value.ObjectId,
29     code: u32,
30     message: []const u8,
31 };
32 
33 pub const DeleteId = struct {
34     id: u32,
35 };
36 
37 pub const Event = union(enum) {
38     fatal: Fatal,
39     delete_id: DeleteId,
40 };
41 
42 pub fn decodeEvent(
43     opcode: u16,
44     payload: []const u8,
45     descriptors: []const @import("sys").fd.Descriptor,
46 ) !Event {
47     const metadata = core.metadata.event(opcode) orelse return error.UnknownOpcode;
48     var decoder = try protocol.value.Decoder.init(metadata, payload, descriptors);
49     const event: Event = switch (opcode) {
50         core.events.@"error".opcode => .{ .fatal = .{
51             .object_id = try decoder.object(),
52             .code = try decoder.unsigned(),
53             .message = try decoder.string(),
54         } },
55         core.events.delete_id.opcode => .{ .delete_id = .{
56             .id = try decoder.unsigned(),
57         } },
58         else => unreachable,
59     };
60     try decoder.finish();
61     return event;
62 }
63 
64 test "display bootstrap requests use generated opcodes" {
65     const std = @import("std");
66 
67     var encoder = try protocol.value.Encoder.init(
68         std.testing.allocator,
69         protocol.value.default_encoder_capacity,
70     );
71     defer encoder.deinit();
72     const callback = try (Sync{ .callback = try .init(2) }).encode(&encoder);
73     try std.testing.expectEqual(@as(u16, 0), callback.opcode());
74     try std.testing.expectEqualSlices(u8, &.{ 2, 0, 0, 0 }, callback.payload);
75     const registry = try (GetRegistry{ .registry = try .init(3) }).encode(&encoder);
76     try std.testing.expectEqual(@as(u16, 1), registry.opcode());
77     try std.testing.expectEqualSlices(u8, &.{ 3, 0, 0, 0 }, registry.payload);
78 }
79 
80 test "display events reject malformed payloads" {
81     const std = @import("std");
82 
83     const delete_payload = [_]u8{ 9, 0, 0, 0 };
84     const event = try decodeEvent(core.events.delete_id.opcode, &delete_payload, &.{});
85     try std.testing.expectEqual(@as(u32, 9), event.delete_id.id);
86     try std.testing.expectError(error.UnknownOpcode, decodeEvent(9, &.{}, &.{}));
87     try std.testing.expectError(
88         error.PayloadTooSmall,
89         decodeEvent(core.events.@"error".opcode, &delete_payload, &.{}),
90     );
91 }