| 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 | |
| 18 | use 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)] |
| 24 | pub 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 | |
| 41 | impl 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(data:"invalid token provided to internal function" ), |
| 46 | Self::IoError(err: &Error) => write!(f, "underlying IO error: {}" , err), |
| 47 | Self::OtherError(err: &Box) => write!(f, "other error during loop operation: {}" , err), |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | impl 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 | |
| 59 | impl 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 | |
| 66 | impl 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: Error) => source, |
| 72 | Error::InvalidToken => Self::new(kind:std::io::ErrorKind::InvalidInput, error:err.to_string()), |
| 73 | Error::OtherError(source: Box) => Self::new(kind:std::io::ErrorKind::Other, error:source), |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | impl 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: &Error) => Some(err), |
| 84 | Self::OtherError(err: &Box) => Some(&**err), |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | /// [`Result`] alias using Calloop's error type. |
| 90 | pub type Result<T> = core::result::Result<T, Error>; |
| 91 | |
| 92 | /// An error generated when trying to insert an event source |
| 93 | pub 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 | |
| 100 | impl<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 | |
| 107 | impl<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 | |
| 114 | impl<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 | |
| 123 | impl<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 | } |
| 129 | |