use anyhow::anyhow;
use fvm_ipld_amt::Error as AmtError;
use fvm_ipld_encoding::Error as EncodingError;
use fvm_ipld_hamt::Error as HamtError;
use fvm_shared4::error::ExitCode;
use crate::v12::ActorError;
pub trait ActorDowncast {
fn downcast_default(self, default_exit_code: ExitCode, msg: impl AsRef<str>) -> ActorError;
fn downcast_wrap(self, msg: impl AsRef<str>) -> anyhow::Error;
}
impl ActorDowncast for anyhow::Error {
fn downcast_default(self, default_exit_code: ExitCode, msg: impl AsRef<str>) -> ActorError {
match downcast_util(self) {
Ok(actor_error) => actor_error.wrap(msg),
Err(other) => {
ActorError::unchecked(default_exit_code, format!("{}: {}", msg.as_ref(), other))
}
}
}
fn downcast_wrap(self, msg: impl AsRef<str>) -> anyhow::Error {
match downcast_util(self) {
Ok(actor_error) => anyhow!(actor_error.wrap(msg)),
Err(other) => anyhow!("{}: {}", msg.as_ref(), other),
}
}
}
impl ActorDowncast for AmtError {
fn downcast_default(self, default_exit_code: ExitCode, msg: impl AsRef<str>) -> ActorError {
match self {
AmtError::Dynamic(e) => e.downcast_default(default_exit_code, msg),
other => {
ActorError::unchecked(default_exit_code, format!("{}: {}", msg.as_ref(), other))
}
}
}
fn downcast_wrap(self, msg: impl AsRef<str>) -> anyhow::Error {
match self {
AmtError::Dynamic(e) => e.downcast_wrap(msg),
other => anyhow!("{}: {}", msg.as_ref(), other),
}
}
}
impl ActorDowncast for HamtError {
fn downcast_default(self, default_exit_code: ExitCode, msg: impl AsRef<str>) -> ActorError {
match self {
HamtError::Dynamic(e) => e.downcast_default(default_exit_code, msg),
other => {
ActorError::unchecked(default_exit_code, format!("{}: {}", msg.as_ref(), other))
}
}
}
fn downcast_wrap(self, msg: impl AsRef<str>) -> anyhow::Error {
match self {
HamtError::Dynamic(e) => e.downcast_wrap(msg),
other => anyhow!("{}: {}", msg.as_ref(), other),
}
}
}
fn downcast_util(error: anyhow::Error) -> anyhow::Result<ActorError> {
let error = match error.downcast::<ActorError>() {
Ok(actor_err) => return Ok(actor_err),
Err(other) => other,
};
let error = match error.downcast::<EncodingError>() {
Ok(enc_error) => {
return Ok(ActorError::unchecked(
ExitCode::USR_SERIALIZATION,
enc_error.to_string(),
))
}
Err(other) => other,
};
let error = match error.downcast::<AmtError>() {
Ok(amt_err) => match amt_err {
AmtError::Dynamic(de) => match downcast_util(de) {
Ok(a) => return Ok(a),
Err(other) => other,
},
other => anyhow!(other),
},
Err(other) => other,
};
let error = match error.downcast::<HamtError>() {
Ok(amt_err) => match amt_err {
HamtError::Dynamic(de) => match downcast_util(de) {
Ok(a) => return Ok(a),
Err(other) => other,
},
other => anyhow!(other),
},
Err(other) => other,
};
Err(error)
}