Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace thiserror with manual impls #186

Merged
merged 3 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pin-utils = { version = "0.1.0", optional = true }
polling = "3.0.0"
slab = "0.4.8"
rustix = { version = "0.38", default-features = false, features = ["event", "fs", "pipe", "std"] }
thiserror = "1.0.7"

[target.'cfg(unix)'.dependencies]
nix = { version = "0.28", default-features = false, features = ["signal"], optional = true }
Expand Down
63 changes: 54 additions & 9 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,52 @@ use std::fmt::{self, Debug, Formatter};
/// The primary error type used by Calloop covering internal errors and I/O
/// errors that arise during loop operations such as source registration or
/// event dispatching.
#[derive(thiserror::Error, Debug)]
#[derive(Debug)]
pub enum Error {
/// When an event source is registered (or re- or un-registered) with the
/// event loop, this error variant will occur if the token Calloop uses to
/// keep track of the event source is not valid.
#[error("invalid token provided to internal function")]
InvalidToken,

/// This variant wraps a [`std::io::Error`], which might arise from
/// Calloop's internal operations.
#[error("underlying IO error")]
IoError(#[from] std::io::Error),
IoError(std::io::Error),

/// Any other unexpected error kind (most likely from a user implementation of
/// [`EventSource::process_events()`]) will be wrapped in this.
///
/// [`EventSource::process_events()`]: crate::EventSource::process_events()
#[error("other error during loop operation")]
OtherError(#[from] Box<dyn std::error::Error + Sync + Send>),
OtherError(Box<dyn std::error::Error + Sync + Send>),
}

impl fmt::Display for Error {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidToken => f.write_str("invalid token provided to internal function"),
Self::IoError(err) => write!(f, "underlying IO error: {}", err),
Self::OtherError(err) => write!(f, "other error during loop operation: {}", err),
}
}
}

impl From<std::io::Error> for Error {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn from(value: std::io::Error) -> Self {
Self::IoError(value)
}
}

impl From<Box<dyn std::error::Error + Sync + Send>> for Error {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn from(value: Box<dyn std::error::Error + Sync + Send>) -> Self {
Self::OtherError(value)
}
}

impl From<Error> for std::io::Error {
/// Converts Calloop's error type into a [`std::io::Error`].
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn from(err: Error) -> Self {
match err {
Error::IoError(source) => source,
Expand All @@ -52,17 +75,25 @@ impl From<Error> for std::io::Error {
}
}

impl std::error::Error for Error {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::InvalidToken => None,
Self::IoError(err) => Some(err),
Self::OtherError(err) => Some(&**err),
}
}
}

/// [`Result`] alias using Calloop's error type.
pub type Result<T> = core::result::Result<T, Error>;

/// An error generated when trying to insert an event source
#[derive(thiserror::Error)]
#[error("error inserting event source")]
pub struct InsertError<T> {
/// The source that could not be inserted
pub inserted: T,
/// The generated error
#[source]
pub error: Error,
}

Expand All @@ -73,6 +104,13 @@ impl<T> Debug for InsertError<T> {
}
}

impl<T> fmt::Display for InsertError<T> {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "error inserting event source: {}", &self.error)
}
}

impl<T> From<InsertError<T>> for crate::Error {
/// Converts the [`InsertError`] into Calloop's error type, throwing away
/// the contained source.
Expand All @@ -81,3 +119,10 @@ impl<T> From<InsertError<T>> for crate::Error {
e.error
}
}

impl<T> std::error::Error for InsertError<T> {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.error)
}
}
18 changes: 16 additions & 2 deletions src/sources/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! A synchronous version of the channel is provided by [`sync_channel`], in which
//! the [`SyncSender`] will block when the channel is full.

use std::fmt;
use std::sync::mpsc;

use crate::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory};
Expand Down Expand Up @@ -213,10 +214,23 @@ impl<T> EventSource for Channel<T> {
}

/// An error arising from processing events for a channel.
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
#[derive(Debug)]
pub struct ChannelError(PingError);

impl fmt::Display for ChannelError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

impl std::error::Error for ChannelError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
29 changes: 24 additions & 5 deletions src/sources/futures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use async_task::{Builder, Runnable};
use slab::Slab;
use std::{
cell::RefCell,
fmt,
future::Future,
rc::Rc,
sync::{
Expand Down Expand Up @@ -248,10 +249,18 @@ impl<T> Drop for Executor<T> {

/// Error generated when trying to schedule a future after the
/// executor was destroyed.
#[derive(thiserror::Error, Debug)]
#[error("the executor was destroyed")]
#[derive(Debug)]
pub struct ExecutorDestroyed;

impl fmt::Display for ExecutorDestroyed {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("the executor was destroyed")
}
}

impl std::error::Error for ExecutorDestroyed {}

/// Create a new executor, and its associated scheduler
///
/// May fail due to OS errors preventing calloop to setup its internal pipes (if your
Expand Down Expand Up @@ -371,17 +380,27 @@ impl<T> EventSource for Executor<T> {
}

/// An error arising from processing events in an async executor event source.
#[derive(thiserror::Error, Debug)]
#[derive(Debug)]
pub enum ExecutorError {
/// Error while reading new futures added via [`Scheduler::schedule()`].
#[error("error adding new futures")]
NewFutureError(ChannelError),

/// Error while processing wake events from existing futures.
#[error("error processing wake events")]
WakeError(PingError),
}

impl fmt::Display for ExecutorError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NewFutureError(err) => write!(f, "error adding new futures: {}", err),
Self::WakeError(err) => write!(f, "error processing wake events: {}", err),
}
}
}

impl std::error::Error for ExecutorError {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
19 changes: 17 additions & 2 deletions src/sources/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ mod pipe;
#[cfg(not(any(target_os = "linux", windows)))]
use pipe as platform;

use std::fmt;

/// Create a new ping event source
///
/// you are given a [`Ping`] instance, which can be cloned and used to ping the
Expand All @@ -56,10 +58,23 @@ pub type Ping = platform::Ping;
pub type PingSource = platform::PingSource;

/// An error arising from processing events for a ping.
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
#[derive(Debug)]
pub struct PingError(Box<dyn std::error::Error + Sync + Send>);

impl fmt::Display for PingError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

impl std::error::Error for PingError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.0)
}
}

#[cfg(test)]
mod tests {
use crate::transient::TransientSource;
Expand Down
18 changes: 16 additions & 2 deletions src/sources/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//! they'll inherit their parent signal mask.

use std::convert::TryFrom;
use std::fmt;
use std::io::Error as IoError;
use std::os::raw::c_int;

Expand Down Expand Up @@ -331,6 +332,19 @@ impl EventSource for Signals {
}

/// An error arising from processing events for a process signal.
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
#[derive(Debug)]
pub struct SignalError(Box<dyn std::error::Error + Sync + Send>);

impl fmt::Display for SignalError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

impl std::error::Error for SignalError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.0)
}
}
Loading