api: unify error handling
Make error infrastructure more backend agnostic and let backends just forward the os errors opaquely.
This commit is contained in:
parent
8db3e0e043
commit
b674d20edf
35 changed files with 507 additions and 630 deletions
224
src/error.rs
224
src/error.rs
|
|
@ -1,45 +1,40 @@
|
|||
use std::{error, fmt};
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use crate::platform_impl;
|
||||
|
||||
// TODO: Rename
|
||||
/// An error that may be generated when requesting Winit state
|
||||
#[derive(Debug)]
|
||||
pub enum ExternalError {
|
||||
/// The operation is not supported by the backend.
|
||||
NotSupported(NotSupportedError),
|
||||
/// The operation was ignored.
|
||||
Ignored,
|
||||
/// The OS cannot perform the operation.
|
||||
Os(OsError),
|
||||
}
|
||||
|
||||
/// The error type for when the requested operation is not supported by the backend.
|
||||
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct NotSupportedError {
|
||||
_marker: (),
|
||||
}
|
||||
|
||||
/// The error type for when the OS cannot perform the requested operation.
|
||||
#[derive(Debug)]
|
||||
pub struct OsError {
|
||||
line: u32,
|
||||
file: &'static str,
|
||||
error: platform_impl::OsError,
|
||||
}
|
||||
|
||||
/// A general error that may occur while running the Winit event loop
|
||||
/// A general error that may occur while running or creating
|
||||
/// the event loop.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum EventLoopError {
|
||||
/// The operation is not supported by the backend.
|
||||
NotSupported(NotSupportedError),
|
||||
/// The OS cannot perform the operation.
|
||||
Os(OsError),
|
||||
/// The event loop can't be re-created.
|
||||
RecreationAttempt,
|
||||
/// Application has exit with an error status.
|
||||
ExitFailure(i32),
|
||||
/// Got unspecified OS-specific error during the request.
|
||||
Os(OsError),
|
||||
/// Creating the event loop with the requested configuration is not supported.
|
||||
NotSupported(NotSupportedError),
|
||||
}
|
||||
|
||||
impl fmt::Display for EventLoopError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::RecreationAttempt => write!(f, "EventLoop can't be recreated"),
|
||||
Self::Os(err) => err.fmt(f),
|
||||
Self::ExitFailure(status) => write!(f, "Exit Failure: {status}"),
|
||||
Self::NotSupported(err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for EventLoopError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
if let Self::Os(err) = self {
|
||||
err.source()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OsError> for EventLoopError {
|
||||
|
|
@ -48,18 +43,102 @@ impl From<OsError> for EventLoopError {
|
|||
}
|
||||
}
|
||||
|
||||
impl NotSupportedError {
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new() -> NotSupportedError {
|
||||
NotSupportedError { _marker: () }
|
||||
impl From<NotSupportedError> for EventLoopError {
|
||||
fn from(value: NotSupportedError) -> Self {
|
||||
Self::NotSupported(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// A general error that may occur during a request to the windowing system.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum RequestError {
|
||||
/// The request is not supported.
|
||||
NotSupported(NotSupportedError),
|
||||
/// The request was ignored by the operating system.
|
||||
Ignored,
|
||||
/// Got unspecified OS specific error during the request.
|
||||
Os(OsError),
|
||||
}
|
||||
|
||||
impl Display for RequestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::NotSupported(err) => err.fmt(f),
|
||||
Self::Ignored => write!(f, "The request was ignored"),
|
||||
Self::Os(err) => err.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Error for RequestError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
if let Self::Os(err) = self {
|
||||
err.source()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NotSupportedError> for RequestError {
|
||||
fn from(value: NotSupportedError) -> Self {
|
||||
Self::NotSupported(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OsError> for RequestError {
|
||||
fn from(value: OsError) -> Self {
|
||||
Self::Os(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// The requested operation is not supported.
|
||||
#[derive(Debug)]
|
||||
pub struct NotSupportedError {
|
||||
/// The reason why a certain operation is not supported.
|
||||
reason: &'static str,
|
||||
}
|
||||
|
||||
impl NotSupportedError {
|
||||
pub(crate) fn new(reason: &'static str) -> Self {
|
||||
Self { reason }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NotSupportedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Operation is not supported: {}", self.reason)
|
||||
}
|
||||
}
|
||||
impl Error for NotSupportedError {}
|
||||
|
||||
/// Unclassified error from the OS.
|
||||
#[derive(Debug)]
|
||||
pub struct OsError {
|
||||
line: u32,
|
||||
file: &'static str,
|
||||
error: Box<dyn Error + Send + Sync + 'static>,
|
||||
}
|
||||
|
||||
impl OsError {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn new(line: u32, file: &'static str, error: platform_impl::OsError) -> OsError {
|
||||
OsError { line, file, error }
|
||||
pub(crate) fn new(
|
||||
line: u32,
|
||||
file: &'static str,
|
||||
error: impl Into<Box<dyn Error + Send + Sync + 'static>>,
|
||||
) -> Self {
|
||||
Self { line, file, error: error.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for OsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad(&format!("os error at {}:{}: {}", self.file, self.line, self.error))
|
||||
}
|
||||
}
|
||||
impl Error for OsError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
Some(self.error.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,64 +148,3 @@ macro_rules! os_error {
|
|||
crate::error::OsError::new(line!(), file!(), $error)
|
||||
}};
|
||||
}
|
||||
|
||||
impl fmt::Display for OsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.pad(&format!("os error at {}:{}: {}", self.file, self.line, self.error))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExternalError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
ExternalError::NotSupported(e) => e.fmt(f),
|
||||
ExternalError::Ignored => write!(f, "Operation was ignored"),
|
||||
ExternalError::Os(e) => e.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for NotSupportedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("NotSupportedError").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NotSupportedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
f.pad("the requested operation is not supported by Winit")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for EventLoopError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
EventLoopError::RecreationAttempt => write!(f, "EventLoop can't be recreated"),
|
||||
EventLoopError::NotSupported(e) => e.fmt(f),
|
||||
EventLoopError::Os(e) => e.fmt(f),
|
||||
EventLoopError::ExitFailure(status) => write!(f, "Exit Failure: {status}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for OsError {}
|
||||
impl error::Error for ExternalError {}
|
||||
impl error::Error for NotSupportedError {}
|
||||
impl error::Error for EventLoopError {}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// Eat attributes for testing
|
||||
#[test]
|
||||
fn ensure_fmt_does_not_panic() {
|
||||
let _ = format!("{:?}, {}", NotSupportedError::new(), NotSupportedError::new().clone());
|
||||
let _ = format!(
|
||||
"{:?}, {}",
|
||||
ExternalError::NotSupported(NotSupportedError::new()),
|
||||
ExternalError::NotSupported(NotSupportedError::new())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue