calloop/
error.rs

1//! Error types used and generated by Calloop.
2//!
3//! This module contains error types for Calloop's operations. They are designed
4//! to make it easy to deal with errors arising from Calloop's internal I/O and
5//! other operations.
6//!
7//! There are two top-level error types:
8//!
9//! - [`Error`]: used by callback functions, internal operations, and some event
10//!   loop API calls
11//!
12//! - [`InsertError`]: used primarily by the [`insert_source()`] method when an
13//!   event source cannot be added to the loop and needs to be given back to the
14//!   caller
15//!
16//! [`insert_source()`]: crate::LoopHandle::insert_source()
17
18use std::fmt::{self, Debug, Formatter};
19
20/// The primary error type used by Calloop covering internal errors and I/O
21/// errors that arise during loop operations such as source registration or
22/// event dispatching.
23#[derive(Debug)]
24pub enum Error {
25    /// When an event source is registered (or re- or un-registered) with the
26    /// event loop, this error variant will occur if the token Calloop uses to
27    /// keep track of the event source is not valid.
28    InvalidToken,
29
30    /// This variant wraps a [`std::io::Error`], which might arise from
31    /// Calloop's internal operations.
32    IoError(std::io::Error),
33
34    /// Any other unexpected error kind (most likely from a user implementation of
35    /// [`EventSource::process_events()`]) will be wrapped in this.
36    ///
37    /// [`EventSource::process_events()`]: crate::EventSource::process_events()
38    OtherError(Box<dyn std::error::Error + Sync + Send>),
39}
40
41impl fmt::Display for Error {
42    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
43    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
44        match self {
45            Self::InvalidToken => f.write_str("invalid token provided to internal function"),
46            Self::IoError(err) => write!(f, "underlying IO error: {}", err),
47            Self::OtherError(err) => write!(f, "other error during loop operation: {}", err),
48        }
49    }
50}
51
52impl From<std::io::Error> for Error {
53    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
54    fn from(value: std::io::Error) -> Self {
55        Self::IoError(value)
56    }
57}
58
59impl From<Box<dyn std::error::Error + Sync + Send>> for Error {
60    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
61    fn from(value: Box<dyn std::error::Error + Sync + Send>) -> Self {
62        Self::OtherError(value)
63    }
64}
65
66impl From<Error> for std::io::Error {
67    /// Converts Calloop's error type into a [`std::io::Error`].
68    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
69    fn from(err: Error) -> Self {
70        match err {
71            Error::IoError(source) => source,
72            Error::InvalidToken => Self::new(std::io::ErrorKind::InvalidInput, err.to_string()),
73            Error::OtherError(source) => Self::new(std::io::ErrorKind::Other, source),
74        }
75    }
76}
77
78impl std::error::Error for Error {
79    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
80    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
81        match self {
82            Self::InvalidToken => None,
83            Self::IoError(err) => Some(err),
84            Self::OtherError(err) => Some(&**err),
85        }
86    }
87}
88
89/// [`Result`] alias using Calloop's error type.
90pub type Result<T> = core::result::Result<T, Error>;
91
92/// An error generated when trying to insert an event source
93pub struct InsertError<T> {
94    /// The source that could not be inserted
95    pub inserted: T,
96    /// The generated error
97    pub error: Error,
98}
99
100impl<T> Debug for InsertError<T> {
101    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
102    fn fmt(&self, formatter: &mut Formatter) -> core::result::Result<(), fmt::Error> {
103        write!(formatter, "{:?}", self.error)
104    }
105}
106
107impl<T> fmt::Display for InsertError<T> {
108    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
109    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
110        write!(f, "error inserting event source: {}", &self.error)
111    }
112}
113
114impl<T> From<InsertError<T>> for crate::Error {
115    /// Converts the [`InsertError`] into Calloop's error type, throwing away
116    /// the contained source.
117    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
118    fn from(e: InsertError<T>) -> crate::Error {
119        e.error
120    }
121}
122
123impl<T> std::error::Error for InsertError<T> {
124    #[cfg_attr(feature = "nightly_coverage", coverage(off))]
125    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
126        Some(&self.error)
127    }
128}