use std::fmt;
use super::Error;
#[non_exhaustive]
pub enum ScopeError<T, E> {
Creation(Error),
Operation(E),
Cleanup {
value: T,
cleanup: Error,
},
OperationAndCleanup {
operation: E,
cleanup: Error,
},
}
impl<T, E> ScopeError<T, E> {
pub fn into_operation(self) -> Option<E> {
match self {
Self::Operation(operation) | Self::OperationAndCleanup { operation, .. } => {
Some(operation)
}
Self::Creation(_) | Self::Cleanup { .. } => None,
}
}
pub fn into_value(self) -> Option<T> {
match self {
Self::Cleanup { value, .. } => Some(value),
Self::Creation(_) | Self::Operation(_) | Self::OperationAndCleanup { .. } => None,
}
}
#[must_use]
pub const fn tmux_error(&self) -> Option<&Error> {
match self {
Self::Creation(error)
| Self::Cleanup { cleanup: error, .. }
| Self::OperationAndCleanup { cleanup: error, .. } => Some(error),
Self::Operation(_) => None,
}
}
}
impl<T: fmt::Debug, E: fmt::Debug> fmt::Debug for ScopeError<T, E> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Creation(error) => formatter.debug_tuple("Creation").field(error).finish(),
Self::Operation(error) => formatter.debug_tuple("Operation").field(error).finish(),
Self::Cleanup { value, cleanup } => formatter
.debug_struct("Cleanup")
.field("value", value)
.field("cleanup", cleanup)
.finish(),
Self::OperationAndCleanup { operation, cleanup } => formatter
.debug_struct("OperationAndCleanup")
.field("operation", operation)
.field("cleanup", cleanup)
.finish(),
}
}
}
impl<T, E: fmt::Display> fmt::Display for ScopeError<T, E> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Creation(error) => write!(formatter, "scoped resource creation failed: {error}"),
Self::Operation(error) => write!(formatter, "scoped operation failed: {error}"),
Self::Cleanup { cleanup, .. } => {
write!(formatter, "scoped resource cleanup failed: {cleanup}")
}
Self::OperationAndCleanup { operation, cleanup } => write!(
formatter,
"scoped operation failed: {operation}; cleanup also failed: {cleanup}"
),
}
}
}
impl<T: fmt::Debug, E: fmt::Debug + fmt::Display> std::error::Error for ScopeError<T, E> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Creation(error) => Some(error),
Self::Cleanup { cleanup, .. } | Self::OperationAndCleanup { cleanup, .. } => {
Some(cleanup)
}
Self::Operation(_) => None,
}
}
}