Use the SwResultExt trait in more places

This commit is contained in:
jtnunley 2023-04-06 11:09:47 -07:00
parent 379910cb8e
commit 74a3357ce8
4 changed files with 65 additions and 99 deletions

View file

@ -1,5 +1,6 @@
use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use std::error::Error; use std::error::Error;
use std::fmt;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use thiserror::Error; use thiserror::Error;
@ -39,16 +40,41 @@ pub enum SoftBufferError {
PlatformError(Option<String>, Option<Box<dyn Error>>), PlatformError(Option<String>, Option<Box<dyn Error>>),
} }
#[allow(unused)] // This isn't used on all platforms /// Convenient wrapper to cast errors into SoftBufferError.
pub(crate) fn unwrap<T, E: std::error::Error + 'static>( pub(crate) trait SwResultExt<T> {
res: Result<T, E>, fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError>;
str: &str, }
) -> Result<T, SoftBufferError> {
match res { impl<T, E: std::error::Error + 'static> SwResultExt<T> for Result<T, E> {
Ok(t) => Ok(t), fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError> {
Err(e) => Err(SoftBufferError::PlatformError( self.map_err(|e| {
Some(str.into()), SoftBufferError::PlatformError(Some(msg.into()), Some(Box::new(LibraryError(e))))
Some(Box::new(e)), })
)),
} }
} }
impl<T> SwResultExt<T> for Option<T> {
fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError> {
self.ok_or_else(|| SoftBufferError::PlatformError(Some(msg.into()), None))
}
}
/// A wrapper around a library error.
///
/// This prevents `x11-dl` and `x11rb` from becoming public dependencies, since users cannot downcast
/// to this type.
struct LibraryError<E>(E);
impl<E: fmt::Debug> fmt::Debug for LibraryError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<E: fmt::Display> fmt::Display for LibraryError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl<E: fmt::Debug + fmt::Display> std::error::Error for LibraryError<E> {}

View file

@ -1,4 +1,4 @@
use crate::{error::unwrap, util, SoftBufferError}; use crate::{error::SwResultExt, util, SoftBufferError};
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle}; use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
use std::{ use std::{
cell::RefCell, cell::RefCell,
@ -29,15 +29,12 @@ impl WaylandDisplayImpl {
// SAFETY: Ensured by user // SAFETY: Ensured by user
let backend = unsafe { Backend::from_foreign_display(display_handle.display as *mut _) }; let backend = unsafe { Backend::from_foreign_display(display_handle.display as *mut _) };
let conn = Connection::from_backend(backend); let conn = Connection::from_backend(backend);
let (globals, event_queue) = unwrap( let (globals, event_queue) =
registry_queue_init(&conn), registry_queue_init(&conn).swbuf_err("Failed to make round trip to server")?;
"Failed to make round trip to server",
)?;
let qh = event_queue.handle(); let qh = event_queue.handle();
let shm: wl_shm::WlShm = unwrap( let shm: wl_shm::WlShm = globals
globals.bind(&qh, 1..=1, ()), .bind(&qh, 1..=1, ())
"Failed to instantiate Wayland Shm", .swbuf_err("Failed to instantiate Wayland Shm")?;
)?;
Ok(Self { Ok(Self {
conn, conn,
event_queue: RefCell::new(event_queue), event_queue: RefCell::new(event_queue),
@ -60,19 +57,15 @@ impl WaylandImpl {
display: Rc<WaylandDisplayImpl>, display: Rc<WaylandDisplayImpl>,
) -> Result<Self, SoftBufferError> { ) -> Result<Self, SoftBufferError> {
// SAFETY: Ensured by user // SAFETY: Ensured by user
let surface_id = unwrap( let surface_id = unsafe {
unsafe { ObjectId::from_ptr(
ObjectId::from_ptr( wl_surface::WlSurface::interface(),
wl_surface::WlSurface::interface(), window_handle.surface as _,
window_handle.surface as _, )
) }
}, .swbuf_err("Failed to create proxy for surface ID.")?;
"Failed to create proxy for surface ID.", let surface = wl_surface::WlSurface::from_id(&display.conn, surface_id)
)?; .swbuf_err("Failed to create proxy for surface ID.")?;
let surface = unwrap(
wl_surface::WlSurface::from_id(&display.conn, surface_id),
"Failed to create proxy for surface ID.",
)?;
Ok(Self { Ok(Self {
display, display,
surface, surface,

View file

@ -8,6 +8,7 @@ use web_sys::CanvasRenderingContext2d;
use web_sys::HtmlCanvasElement; use web_sys::HtmlCanvasElement;
use web_sys::ImageData; use web_sys::ImageData;
use crate::error::SwResultExt;
use crate::SoftBufferError; use crate::SoftBufferError;
use std::convert::TryInto; use std::convert::TryInto;
use std::num::NonZeroU32; use std::num::NonZeroU32;
@ -22,19 +23,9 @@ pub struct WebDisplayImpl {
impl WebDisplayImpl { impl WebDisplayImpl {
pub(super) fn new() -> Result<Self, SoftBufferError> { pub(super) fn new() -> Result<Self, SoftBufferError> {
let document = web_sys::window() let document = web_sys::window()
.ok_or_else(|| { .swbuf_err("`window` is not present in this runtime")?
SoftBufferError::PlatformError(
Some("`window` is not present in this runtime".into()),
None,
)
})?
.document() .document()
.ok_or_else(|| { .swbuf_err("`document` is not present in this runtime")?;
SoftBufferError::PlatformError(
Some("`document` is not present in this runtime".into()),
None,
)
})?;
Ok(Self { document }) Ok(Self { document })
} }
@ -61,31 +52,19 @@ impl WebImpl {
.query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id)) .query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id))
// `querySelector` only throws an error if the selector is invalid. // `querySelector` only throws an error if the selector is invalid.
.unwrap() .unwrap()
.ok_or_else(|| { .swbuf_err("No canvas found with the given id")?
SoftBufferError::PlatformError(
Some("No canvas found with the given id".into()),
None,
)
})?
// We already made sure this was a canvas in `querySelector`. // We already made sure this was a canvas in `querySelector`.
.unchecked_into(); .unchecked_into();
let ctx = canvas let ctx = canvas
.get_context("2d") .get_context("2d")
.map_err(|_| { .ok()
SoftBufferError::PlatformError( .swbuf_err("Canvas already controlled using `OffscreenCanvas`")?
Some("Canvas already controlled using `OffscreenCanvas`".into()), .swbuf_err(
None, "A canvas context other than `CanvasRenderingContext2d` was already created",
) )?
})? .dyn_into()
.ok_or_else(|| { .expect("`getContext(\"2d\") didn't return a `CanvasRenderingContext2d`");
SoftBufferError::PlatformError(
Some("A canvas context other than `CanvasRenderingContext2d` was already created".into()),
None,
)
})?
.dyn_into()
.expect("`getContext(\"2d\") didn't return a `CanvasRenderingContext2d`");
Ok(Self { Ok(Self {
canvas, canvas,

View file

@ -5,6 +5,7 @@
#![allow(clippy::uninlined_format_args)] #![allow(clippy::uninlined_format_args)]
use crate::error::SwResultExt;
use crate::{util, SoftBufferError}; use crate::{util, SoftBufferError};
use nix::libc::{shmat, shmctl, shmdt, shmget, IPC_PRIVATE, IPC_RMID}; use nix::libc::{shmat, shmctl, shmdt, shmget, IPC_PRIVATE, IPC_RMID};
use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle}; use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle};
@ -650,19 +651,6 @@ impl From<io::Error> for PushBufferError {
} }
} }
/// Convenient wrapper to cast errors into SoftBufferError.
trait SwResultExt<T, E> {
fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError>;
}
impl<T, E: std::error::Error + 'static> SwResultExt<T, E> for Result<T, E> {
fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError> {
self.map_err(|e| {
SoftBufferError::PlatformError(Some(msg.into()), Some(Box::new(LibraryError(e))))
})
}
}
/// Convenient wrapper to cast errors into PushBufferError. /// Convenient wrapper to cast errors into PushBufferError.
trait PushResultExt<T, E> { trait PushResultExt<T, E> {
fn push_err(self) -> Result<T, PushBufferError>; fn push_err(self) -> Result<T, PushBufferError>;
@ -674,26 +662,6 @@ impl<T, E: Into<PushBufferError>> PushResultExt<T, E> for Result<T, E> {
} }
} }
/// A wrapper around a library error.
///
/// This prevents `x11-dl` and `x11rb` from becoming public dependencies, since users cannot downcast
/// to this type.
struct LibraryError<E>(E);
impl<E: fmt::Debug> fmt::Debug for LibraryError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl<E: fmt::Display> fmt::Display for LibraryError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl<E: fmt::Debug + fmt::Display> std::error::Error for LibraryError<E> {}
/// Get the length that a slice needs to be to hold a buffer of the given dimensions. /// Get the length that a slice needs to be to hold a buffer of the given dimensions.
#[inline(always)] #[inline(always)]
fn total_len(width: u16, height: u16) -> usize { fn total_len(width: u16, height: u16) -> usize {