Skip to main content

base_scheduler/
operation_error.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::Cancelled;
5use std::{fmt, io};
6
7/// Cooperative cancellation is distinct from an operating-system error.
8#[derive(Debug)]
9pub enum OperationError {
10    /// The operation observed a cooperative cancellation request.
11    Cancelled(Cancelled),
12    /// The operation failed with an I/O error, including resolver failures carried as [`AddressResolveError`](crate::AddressResolveError).
13    Io(io::Error),
14}
15
16/// An operation's result, preserving cancellation separately from I/O failure.
17pub type OperationResult<T> = Result<T, OperationError>;
18
19impl OperationError {
20    /// I/O-compatible classification; match `Cancelled` to distinguish a cooperative request from an OS interruption.
21    pub fn kind(&self) -> io::ErrorKind {
22        match self {
23            Self::Cancelled(_) => io::ErrorKind::Interrupted,
24            Self::Io(error) => error.kind(),
25        }
26    }
27
28    /// The OS error code of an `Io` error, or `None` for cancellation and errors without one.
29    pub fn raw_os_error(&self) -> Option<i32> {
30        match self {
31            Self::Cancelled(_) => None,
32            Self::Io(error) => error.raw_os_error(),
33        }
34    }
35}
36
37impl fmt::Display for OperationError {
38    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::Cancelled(error) => error.fmt(formatter),
41            Self::Io(error) => error.fmt(formatter),
42        }
43    }
44}
45
46impl std::error::Error for OperationError {
47    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
48        Some(match self {
49            Self::Cancelled(error) => error,
50            Self::Io(error) => error,
51        })
52    }
53}
54
55impl From<io::Error> for OperationError {
56    fn from(error: io::Error) -> Self {
57        Self::Io(error)
58    }
59}
60
61impl From<Cancelled> for OperationError {
62    fn from(error: Cancelled) -> Self {
63        Self::Cancelled(error)
64    }
65}
66
67impl From<OperationError> for io::Error {
68    fn from(error: OperationError) -> Self {
69        match error {
70            OperationError::Io(error) => error,
71            OperationError::Cancelled(error) => Self::new(io::ErrorKind::Interrupted, error),
72        }
73    }
74}