use std::error::Error;
use std::fmt::{self, Display};
use crate::data_transfer::DataTransferId;
#[derive(Debug)]
#[non_exhaustive]
pub enum EventLoopError {
RecreationAttempt,
ExitFailure(i32),
Os(OsError),
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, only a single instance of it is supported (for \
cross-platform compatibility)"
)
},
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 {
fn from(value: OsError) -> Self {
Self::Os(value)
}
}
impl From<NotSupportedError> for EventLoopError {
fn from(value: NotSupportedError) -> Self {
Self::NotSupported(value)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum CreateWindowError {
PopupNotSupported,
InvalidAttribute(InvalidInput),
Os(OsError),
}
impl Display for CreateWindowError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PopupNotSupported => write!(f, "WindowType::Popup is not supported"),
Self::InvalidAttribute(InvalidInput { reason }) => {
write!(f, "Invalid WindowAttributes: {reason}")
},
Self::Os(err) => err.fmt(f),
}
}
}
impl Error for CreateWindowError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let Self::Os(err) = self { err.source() } else { None }
}
}
impl From<InvalidInput> for CreateWindowError {
fn from(value: InvalidInput) -> Self {
Self::InvalidAttribute(value)
}
}
impl From<OsError> for CreateWindowError {
fn from(value: OsError) -> Self {
Self::Os(value)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum TransferError {
NotSupported(NotSupportedError),
UnknownTransfer(DataTransferId),
Failed,
Os(OsError),
}
impl Display for TransferError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotSupported(err) => err.fmt(f),
Self::UnknownTransfer(id) => {
write!(f, "Unknown data transfer with ID {}", id.into_raw())
},
Self::Failed => write!(f, "Transfer request failed"),
Self::Os(err) => err.fmt(f),
}
}
}
impl Error for TransferError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let Self::Os(err) = self { err.source() } else { None }
}
}
impl From<NotSupportedError> for TransferError {
fn from(value: NotSupportedError) -> Self {
Self::NotSupported(value)
}
}
impl From<OsError> for TransferError {
fn from(value: OsError) -> Self {
Self::Os(value)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum CustomCursorError {
NotSupported,
UnsupportedSource,
Os(OsError),
}
impl Display for CustomCursorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotSupported => write!(f, "create_custom_cursor is not supported"),
Self::UnsupportedSource => {
write!(f, "the provided CustomCursorSource is not supported")
},
Self::Os(err) => err.fmt(f),
}
}
}
impl Error for CustomCursorError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let Self::Os(err) = self { err.source() } else { None }
}
}
impl From<OsError> for CustomCursorError {
fn from(value: OsError) -> Self {
Self::Os(value)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum RequestError {
NotSupported(NotSupportedError),
Os(OsError),
}
impl Display for RequestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotSupported(err) => err.fmt(f),
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)
}
}
#[derive(Debug)]
pub struct InvalidInput {
reason: &'static str,
}
impl InvalidInput {
pub const fn new(reason: &'static str) -> Self {
Self { reason }
}
}
impl fmt::Display for InvalidInput {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Invalid input: {}", self.reason)
}
}
impl Error for InvalidInput {}
#[derive(Debug)]
pub struct NotSupportedError {
reason: &'static str,
}
impl NotSupportedError {
pub const 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 {}
#[derive(Debug)]
pub struct InternalError {
source: &'static str,
}
impl InternalError {
pub const fn new(source: &'static str) -> Self {
Self { source }
}
}
impl fmt::Display for InternalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Internal error: {}", self.source)
}
}
impl Error for InternalError {}
#[derive(Debug)]
pub struct OsError {
line: u32,
file: &'static str,
error: Box<dyn Error + Send + Sync + 'static>,
}
impl OsError {
pub 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())
}
}
#[allow(unused_macros)]
macro_rules! os_error {
($error:expr) => {{ crate::error::OsError::new(line!(), file!(), $error) }};
}