use std::error::Error;
use std::fmt;
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum BuildError {
DuplicateOperation {
name: String,
},
DuplicateHandler {
name: String,
},
MissingDescriptor {
name: String,
},
MissingHandler {
name: String,
},
InvalidModule {
name: String,
message: String,
},
InvalidOperation {
name: String,
message: String,
},
InvalidHandler {
name: String,
message: String,
},
}
impl BuildError {
#[must_use]
pub fn duplicate_operation(name: impl Into<String>) -> Self {
Self::DuplicateOperation { name: name.into() }
}
#[must_use]
pub fn duplicate_handler(name: impl Into<String>) -> Self {
Self::DuplicateHandler { name: name.into() }
}
#[must_use]
pub fn missing_descriptor(name: impl Into<String>) -> Self {
Self::MissingDescriptor { name: name.into() }
}
#[must_use]
pub fn missing_handler(name: impl Into<String>) -> Self {
Self::MissingHandler { name: name.into() }
}
#[must_use]
pub fn invalid_module(name: impl Into<String>, message: impl Into<String>) -> Self {
Self::InvalidModule {
name: name.into(),
message: message.into(),
}
}
#[must_use]
pub fn invalid_operation(name: impl Into<String>, message: impl Into<String>) -> Self {
Self::InvalidOperation {
name: name.into(),
message: message.into(),
}
}
#[must_use]
pub fn invalid_handler(name: impl Into<String>, message: impl Into<String>) -> Self {
Self::InvalidHandler {
name: name.into(),
message: message.into(),
}
}
}
impl fmt::Display for BuildError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::DuplicateOperation { name } => {
write!(f, "operation `{name}` is already registered")
}
Self::DuplicateHandler { name } => {
write!(f, "handler for operation `{name}` is already registered")
}
Self::MissingDescriptor { name } => {
write!(f, "handler `{name}` has no matching operation descriptor")
}
Self::MissingHandler { name } => {
write!(f, "operation `{name}` has no registered handler")
}
Self::InvalidModule { name, message } => {
write!(f, "module `{name}` is invalid: {message}")
}
Self::InvalidOperation { name, message } => {
write!(f, "operation `{name}` is invalid: {message}")
}
Self::InvalidHandler { name, message } => {
write!(f, "handler `{name}` is invalid: {message}")
}
}
}
}
impl Error for BuildError {}
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct ReceiptSinkHandlerCause {
pub code: String,
pub message: String,
}
impl ReceiptSinkHandlerCause {
#[must_use]
pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
Self {
code: code.into(),
message: message.into(),
}
}
#[must_use]
pub fn code(&self) -> &str {
&self.code
}
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum RuntimeError {
UnknownOperation {
name: String,
},
MissingHandler {
name: String,
},
Handler {
name: String,
code: String,
message: String,
},
ReceiptSink {
name: String,
message: String,
caused_by_handler: Option<ReceiptSinkHandlerCause>,
},
}
impl RuntimeError {
#[must_use]
pub fn unknown_operation(name: impl Into<String>) -> Self {
Self::UnknownOperation { name: name.into() }
}
#[must_use]
pub fn missing_handler(name: impl Into<String>) -> Self {
Self::MissingHandler { name: name.into() }
}
#[must_use]
pub fn handler(
name: impl Into<String>,
code: impl Into<String>,
message: impl Into<String>,
) -> Self {
Self::Handler {
name: name.into(),
code: code.into(),
message: message.into(),
}
}
#[must_use]
pub fn receipt_sink(name: impl Into<String>, message: impl Into<String>) -> Self {
Self::ReceiptSink {
name: name.into(),
message: message.into(),
caused_by_handler: None,
}
}
#[must_use]
pub fn receipt_sink_after_handler_failure(
name: impl Into<String>,
message: impl Into<String>,
cause: ReceiptSinkHandlerCause,
) -> Self {
Self::ReceiptSink {
name: name.into(),
message: message.into(),
caused_by_handler: Some(cause),
}
}
}
impl fmt::Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::UnknownOperation { name } => write!(f, "unknown operation `{name}`"),
Self::MissingHandler { name } => {
write!(f, "operation `{name}` has no registered handler")
}
Self::Handler {
name,
code,
message,
} => {
write!(
f,
"handler for operation `{name}` failed with {code}: {message}"
)
}
Self::ReceiptSink {
name,
message,
caused_by_handler,
} => {
if let Some(cause) = caused_by_handler {
write!(
f,
"receipt sink for operation `{name}` failed after handler error {}: {}: {message}",
cause.code(),
cause.message()
)
} else {
write!(f, "receipt sink for operation `{name}` failed: {message}")
}
}
}
}
}
impl Error for RuntimeError {}