use crate::transport::Step;
use dbsp::storage::backend::{StorageError, StoragePath};
use serde::{Serialize, Serializer};
use std::backtrace::Backtrace;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::ErrorKind;
pub use crate::errors::controller::ControllerError;
#[derive(Debug, Serialize)]
#[serde(untagged)]
#[doc(hidden)]
pub enum StepError {
StorageError {
path: String,
error: StorageError,
#[serde(serialize_with = "serialize_as_string")]
backtrace: Backtrace,
},
EncodeError {
path: String,
#[serde(serialize_with = "serialize_as_string")]
error: rmp_serde::encode::Error,
},
DecodeError {
path: String,
#[serde(serialize_with = "serialize_as_string")]
error: rmp_serde::decode::Error,
},
WrongStep {
path: String,
expected: Step,
found: Step,
},
}
impl StepError {
#[doc(hidden)]
pub fn kind(&self) -> ErrorKind {
match self {
Self::StorageError { error, .. } => error.kind(),
Self::EncodeError { .. } | Self::DecodeError { .. } | Self::WrongStep { .. } => {
ErrorKind::Other
}
}
}
}
fn serialize_as_string<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: ToString,
{
serializer.serialize_str(&value.to_string())
}
impl Display for StepError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
StepError::EncodeError { path, error } => {
write!(f, "{path}: error writing step ({error})")
}
StepError::DecodeError { path, error } => {
write!(f, "{path}: error parsing step ({error})")
}
StepError::StorageError { path, error, .. } => write!(f, "{path}: {error}"),
StepError::WrongStep {
path,
expected,
found,
} => write!(
f,
"{path}: file should contain step {expected}, but read step {found}"
),
}
}
}
impl StepError {
#[doc(hidden)]
pub fn storage_error(path: &StoragePath, error: StorageError) -> StepError {
StepError::StorageError {
path: path.as_ref().into(),
error,
backtrace: Backtrace::capture(),
}
}
}
impl From<StepError> for ControllerError {
fn from(value: StepError) -> Self {
ControllerError::StepError(value)
}
}