use raw_window_handle::{HandleError, RawDisplayHandle, RawWindowHandle};
use std::error::Error;
use std::fmt;
use std::num::NonZeroU32;
#[derive(Debug)]
#[non_exhaustive]
pub enum SoftBufferError {
RawWindowHandle(HandleError),
UnsupportedDisplayPlatform {
human_readable_display_platform_name: &'static str,
display_handle: RawDisplayHandle,
},
UnsupportedWindowPlatform {
human_readable_window_platform_name: &'static str,
human_readable_display_platform_name: &'static str,
window_handle: RawWindowHandle,
},
IncompleteWindowHandle,
IncompleteDisplayHandle,
SizeOutOfRange {
width: NonZeroU32,
height: NonZeroU32,
},
DamageOutOfRange {
rect: crate::Rect,
},
PlatformError(Option<String>, Option<Box<dyn Error>>),
Unimplemented,
}
impl fmt::Display for SoftBufferError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::RawWindowHandle(err) => fmt::Display::fmt(err, f),
Self::UnsupportedDisplayPlatform {
human_readable_display_platform_name,
display_handle,
} => write!(
f,
"The provided display returned an unsupported platform: {}.\nDisplay handle: {:?}",
human_readable_display_platform_name, display_handle
),
Self::UnsupportedWindowPlatform {
human_readable_window_platform_name,
human_readable_display_platform_name,
window_handle,
} => write!(
f,
"The provided window returned an unsupported platform: {}, {}.\nWindow handle: {:?}",
human_readable_window_platform_name, human_readable_display_platform_name, window_handle
),
Self::IncompleteWindowHandle => write!(f, "The provided window handle is null."),
Self::IncompleteDisplayHandle => write!(f, "The provided display handle is null."),
Self::SizeOutOfRange { width, height } => write!(
f,
"Surface size {width}x{height} out of range for backend.",
),
Self::PlatformError(msg, None) => write!(f, "Platform error: {msg:?}"),
Self::PlatformError(msg, Some(err)) => write!(f, "Platform error: {msg:?}: {err}"),
Self::DamageOutOfRange { rect } => write!(
f,
"Damage rect {}x{} at ({}, {}) out of range for backend.",
rect.width, rect.height, rect.x, rect.y
),
Self::Unimplemented => write!(f, "This function is unimplemented on this platform."),
}
}
}
impl std::error::Error for SoftBufferError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::RawWindowHandle(err) => Some(err),
Self::PlatformError(_, err) => err.as_deref(),
_ => None,
}
}
}
impl From<HandleError> for SoftBufferError {
fn from(err: HandleError) -> Self {
Self::RawWindowHandle(err)
}
}
pub(crate) enum InitError<D> {
Failure(SoftBufferError),
Unsupported(D),
}
impl<T> From<SoftBufferError> for InitError<T> {
fn from(err: SoftBufferError) -> Self {
Self::Failure(err)
}
}
impl<T> From<HandleError> for InitError<T> {
fn from(err: HandleError) -> Self {
Self::Failure(err.into())
}
}
#[allow(dead_code)]
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))
}
}
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> {}