Rework wrapping of wl_display functions

With the way libwayland uses errno, it isn't feasible for me to
determine exactly which errno values are possible after libwayland
function calls in most cases. Returning the full errno enum provided
by the zig standard and allowing the users to check for only those
values they care to handle differently is the most robust way to use
thesl APIs.

This change makes it so that the "number of events dispatched"
is no longer available, but I'm not aware of any use-case for this
information.
This commit is contained in:
Isaac Freund
2022-04-25 19:24:32 +02:00
parent f4ca39015b
commit 5dd0ba638a
+22 -98
View File
@@ -1,10 +1,10 @@
extern fn wl_display_connect(name: ?[*:0]const u8) ?*Display;
pub fn connect(name: ?[*:0]const u8) error{ConnectFailed}!*Display {
pub inline fn connect(name: ?[*:0]const u8) error{ConnectFailed}!*Display {
return wl_display_connect(name) orelse return error.ConnectFailed;
}
extern fn wl_display_connect_to_fd(fd: c_int) ?*Display;
pub fn connectToFd(fd: c_int) error{ConnectFailed}!*Display {
pub inline fn connectToFd(fd: c_int) error{ConnectFailed}!*Display {
return wl_display_connect_to_fd(fd) orelse return error.ConnectFailed;
}
@@ -15,130 +15,52 @@ extern fn wl_display_get_fd(display: *Display) c_int;
pub const getFd = wl_display_get_fd;
extern fn wl_display_dispatch(display: *Display) c_int;
pub fn dispatch(display: *Display) !u32 {
const rc = wl_display_dispatch(display);
// poll(2), sendmsg(2), recvmsg(2), EOVERFLOW, E2BIG, EPROTO
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
.FAULT => unreachable,
.INTR => unreachable,
.INVAL => unreachable,
.NOMEM => error.SystemResources,
.ACCES => error.AccessDenied,
.AGAIN => unreachable,
.ALREADY => error.FastOpenAlreadyInProgress,
.BADF => unreachable,
.CONNRESET => error.ConnectionResetByPeer,
.DESTADDRREQ => unreachable,
.ISCONN => unreachable,
.MSGSIZE => error.MessageTooBig,
.NOBUFS => error.SystemResources,
.NOTCONN => unreachable,
.NOTSOCK => unreachable,
.OPNOTSUPP => unreachable,
.PIPE => error.BrokenPipe,
.CONNREFUSED => error.ConnectionRefused,
.OVERFLOW => error.BufferOverflow,
.@"2BIG" => error.BufferOverflow,
.PROTO => error.ProtocolError,
else => |err| os.unexpectedErrno(err),
};
pub inline fn dispatch(display: *Display) os.E {
return os.errno(wl_display_dispatch(display));
}
extern fn wl_display_dispatch_queue(display: *Display, queue: *client.wl.EventQueue) c_int;
pub fn dispatchQueue(display: *Display, queue: *client.wl.EventQueue) !u32 {
const rc = wl_display_dispatch_queue(display, queue);
// poll(2), sendmsg(2), recvmsg(2), EOVERFLOW, E2BIG, EPROTO
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
.FAULT => unreachable,
.INTR => unreachable,
.INVAL => unreachable,
.NOMEM => error.SystemResources,
.ACCES => error.AccessDenied,
.AGAIN => unreachable,
.ALREADY => error.FastOpenAlreadyInProgress,
.BADF => unreachable,
.CONNRESET => error.ConnectionResetByPeer,
.DESTADDRREQ => unreachable,
.ISCONN => unreachable,
.MSGSIZE => error.MessageTooBig,
.NOBUFS => error.SystemResources,
.NOTCONN => unreachable,
.NOTSOCK => unreachable,
.OPNOTSUPP => unreachable,
.PIPE => error.BrokenPipe,
.CONNREFUSED => error.ConnectionRefused,
.OVERFLOW => error.BufferOverflow,
.@"2BIG" => error.BufferOverflow,
.PROTO => error.ProtocolError,
else => |err| os.unexpectedErrno(err),
};
pub inline fn dispatchQueue(display: *Display, queue: *client.wl.EventQueue) os.E {
return os.errno(wl_display_dispatch_queue(display, queue));
}
extern fn wl_display_dispatch_pending(display: *Display) c_int;
pub fn dispatchPending(display: *Display) !u32 {
const rc = wl_display_dispatch_pending(display);
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
// TODO
else => |err| os.unexpectedErrno(err),
};
pub inline fn dispatchPending(display: *Display) os.E {
return os.errno(wl_display_dispatch_pending(display));
}
extern fn wl_display_dispatch_queue_pending(display: *Display, queue: *client.wl.EventQueue) c_int;
pub fn dispatchQueuePending(display: *Display, queue: *client.wl.EventQueue) !u32 {
const rc = wl_display_dispatch_queue_pending(display, queue);
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
// TODO
else => |err| os.unexpectedErrno(err),
};
pub inline fn dispatchQueuePending(display: *Display, queue: *client.wl.EventQueue) os.E {
return os.errno(wl_display_dispatch_queue_pending(display, queue));
}
extern fn wl_display_roundtrip(display: *Display) c_int;
pub fn roundtrip(display: *Display) !u32 {
const rc = wl_display_roundtrip(display);
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
// TODO
else => |err| os.unexpectedErrno(err),
};
pub inline fn roundtrip(display: *Display) os.E {
return os.errno(wl_display_roundtrip(display));
}
extern fn wl_display_roundtrip_queue(display: *Display, queue: *client.wl.EventQueue) c_int;
pub fn roundtripQueue(display: *Display, queue: *client.wl.EventQueue) !u32 {
const rc = wl_display_roundtrip_queue(display, queue);
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
// TODO
else => |err| os.unexpectedErrno(err),
};
pub inline fn roundtripQueue(display: *Display, queue: *client.wl.EventQueue) os.E {
return os.errno(wl_display_roundtrip_queue(display, queue));
}
extern fn wl_display_flush(display: *Display) c_int;
pub fn flush(display: *Display) error{WouldBlock}!u32 {
const rc = wl_display_flush(display);
return switch (os.errno(rc)) {
.SUCCESS => @intCast(u32, rc),
.AGAIN => error.WouldBlock,
else => unreachable,
};
pub inline fn flush(display: *Display) os.E {
return os.errno(wl_display_flush(display));
}
extern fn wl_display_create_queue(display: *Display) ?*client.wl.EventQueue;
pub fn createQueue(display: *Display) error{OutOfMemory}!*client.wl.EventQueue {
pub inline fn createQueue(display: *Display) error{OutOfMemory}!*client.wl.EventQueue {
return wl_display_create_queue(display) orelse error.OutOfMemory;
}
// TODO: should we interpret this return value?
extern fn wl_display_get_error(display: *Display) c_int;
pub const getError = wl_display_get_error;
extern fn wl_display_prepare_read_queue(display: *Display, queue: *client.wl.EventQueue) c_int;
/// Succeeds if the queue is empty and returns true.
/// Fails and returns false if the queue was not empty.
pub fn prepareReadQueue(display: *Display, queue: *client.wl.EventQueue) bool {
pub inline fn prepareReadQueue(display: *Display, queue: *client.wl.EventQueue) bool {
switch (wl_display_prepare_read_queue(display, queue)) {
0 => return true,
-1 => return false,
@@ -149,7 +71,7 @@ pub fn prepareReadQueue(display: *Display, queue: *client.wl.EventQueue) bool {
extern fn wl_display_prepare_read(display: *Display) c_int;
/// Succeeds if the queue is empty and returns true.
/// Fails and returns false if the queue was not empty.
pub fn prepareRead(display: *Display) bool {
pub inline fn prepareRead(display: *Display) bool {
switch (wl_display_prepare_read(display)) {
0 => return true,
-1 => return false,
@@ -161,4 +83,6 @@ extern fn wl_display_cancel_read(display: *Display) void;
pub const cancelRead = wl_display_cancel_read;
extern fn wl_display_read_events(display: *Display) c_int;
pub const readEvents = wl_display_read_events;
pub inline fn readEvents(display: *Display) os.E {
return os.errno(wl_display_read_events(display));
}