Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 37 additions & 11 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use std::error::Error;
use std::fmt;
use std::num::NonZeroU32;
use thiserror::Error;

Expand Down Expand Up @@ -39,16 +40,41 @@ pub enum SoftBufferError {
PlatformError(Option<String>, Option<Box<dyn Error>>),
}

#[allow(unused)] // This isn't used on all platforms
pub(crate) fn unwrap<T, E: std::error::Error + 'static>(
res: Result<T, E>,
str: &str,
) -> Result<T, SoftBufferError> {
match res {
Ok(t) => Ok(t),
Err(e) => Err(SoftBufferError::PlatformError(
Some(str.into()),
Some(Box::new(e)),
)),
/// Convenient wrapper to cast errors into SoftBufferError.
pub(crate) trait SwResultExt<T> {
fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError>;
}

impl<T, E: std::error::Error + 'static> SwResultExt<T> 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))))
})
}
}

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> {}
37 changes: 15 additions & 22 deletions src/wayland/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{error::unwrap, util, SoftBufferError};
use crate::{error::SwResultExt, util, SoftBufferError};
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
use std::{
cell::RefCell,
Expand Down Expand Up @@ -29,15 +29,12 @@ impl WaylandDisplayImpl {
// SAFETY: Ensured by user
let backend = unsafe { Backend::from_foreign_display(display_handle.display as *mut _) };
let conn = Connection::from_backend(backend);
let (globals, event_queue) = unwrap(
registry_queue_init(&conn),
"Failed to make round trip to server",
)?;
let (globals, event_queue) =
registry_queue_init(&conn).swbuf_err("Failed to make round trip to server")?;
let qh = event_queue.handle();
let shm: wl_shm::WlShm = unwrap(
globals.bind(&qh, 1..=1, ()),
"Failed to instantiate Wayland Shm",
)?;
let shm: wl_shm::WlShm = globals
.bind(&qh, 1..=1, ())
.swbuf_err("Failed to instantiate Wayland Shm")?;
Ok(Self {
conn,
event_queue: RefCell::new(event_queue),
Expand All @@ -60,19 +57,15 @@ impl WaylandImpl {
display: Rc<WaylandDisplayImpl>,
) -> Result<Self, SoftBufferError> {
// SAFETY: Ensured by user
let surface_id = unwrap(
unsafe {
ObjectId::from_ptr(
wl_surface::WlSurface::interface(),
window_handle.surface as _,
)
},
"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.",
)?;
let surface_id = unsafe {
ObjectId::from_ptr(
wl_surface::WlSurface::interface(),
window_handle.surface as _,
)
}
.swbuf_err("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.")?;
Ok(Self {
display,
surface,
Expand Down
45 changes: 12 additions & 33 deletions src/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use web_sys::CanvasRenderingContext2d;
use web_sys::HtmlCanvasElement;
use web_sys::ImageData;

use crate::error::SwResultExt;
use crate::SoftBufferError;
use std::convert::TryInto;
use std::num::NonZeroU32;
Expand All @@ -22,19 +23,9 @@ pub struct WebDisplayImpl {
impl WebDisplayImpl {
pub(super) fn new() -> Result<Self, SoftBufferError> {
let document = web_sys::window()
.ok_or_else(|| {
SoftBufferError::PlatformError(
Some("`window` is not present in this runtime".into()),
None,
)
})?
.swbuf_err("`window` is not present in this runtime")?
.document()
.ok_or_else(|| {
SoftBufferError::PlatformError(
Some("`document` is not present in this runtime".into()),
None,
)
})?;
.swbuf_err("`document` is not present in this runtime")?;

Ok(Self { document })
}
Expand All @@ -61,31 +52,19 @@ impl WebImpl {
.query_selector(&format!("canvas[data-raw-handle=\"{}\"]", handle.id))
// `querySelector` only throws an error if the selector is invalid.
.unwrap()
.ok_or_else(|| {
SoftBufferError::PlatformError(
Some("No canvas found with the given id".into()),
None,
)
})?
.swbuf_err("No canvas found with the given id")?
// We already made sure this was a canvas in `querySelector`.
.unchecked_into();

let ctx = canvas
.get_context("2d")
.map_err(|_| {
SoftBufferError::PlatformError(
Some("Canvas already controlled using `OffscreenCanvas`".into()),
None,
)
})?
.ok_or_else(|| {
SoftBufferError::PlatformError(
Some("A canvas context other than `CanvasRenderingContext2d` was already created".into()),
None,
)
})?
.dyn_into()
.expect("`getContext(\"2d\") didn't return a `CanvasRenderingContext2d`");
.get_context("2d")
.ok()
.swbuf_err("Canvas already controlled using `OffscreenCanvas`")?
.swbuf_err(
"A canvas context other than `CanvasRenderingContext2d` was already created",
)?
.dyn_into()
.expect("`getContext(\"2d\") didn't return a `CanvasRenderingContext2d`");

Ok(Self {
canvas,
Expand Down
34 changes: 1 addition & 33 deletions src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#![allow(clippy::uninlined_format_args)]

use crate::error::SwResultExt;
use crate::{util, SoftBufferError};
use nix::libc::{shmat, shmctl, shmdt, shmget, IPC_PRIVATE, IPC_RMID};
use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle};
Expand Down Expand Up @@ -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.
trait PushResultExt<T, E> {
fn push_err(self) -> Result<T, PushBufferError>;
Expand All @@ -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.
#[inline(always)]
fn total_len(width: u16, height: u16) -> usize {
Expand Down