use serde_json::Error as SerdeJsonError;
use std::error::Error as StdError;
use std::fmt;
use std::fmt::Debug;
use std::sync::Arc;
type ParentError = Arc<dyn StdError + Send + Sync + 'static>;
#[derive(Clone, Debug)]
pub enum SbError {
Generic,
Message(&'static str),
CustomMessage(String),
CustomError {
message: String,
source: ParentError,
},
Unexpected,
EnvVariableMissing(String),
InvalidKeypairFile,
KeyParseError,
CheckSizeError,
IoError(ParentError),
SgxError,
SgxWriteError,
NetworkError,
QuoteParseError,
InvalidQuoteError,
QvnError(Arc<String>),
DockerError,
DockerFetchError,
FunctionImageTooBigError,
ContainerErrorMessage(String),
ContainerError(ParentError),
ContainerStartError(ParentError),
ContainerCreateError(ParentError),
ContainerNeedsUpdate,
ContainerResultParseError,
AttachError,
ContainerTimeout,
ContainerActive,
ContainerBackoff(u64),
FunctionErrorCountExceeded(u32),
FunctionResultParseError,
IllegalFunctionOutput,
FunctionVerifyFailure,
FunctionResultIllegalAccount,
FunctionResultAccountsMismatch,
FunctionResultInvalidData,
FunctionResultInvalidPid,
FunctionResultEmptyInstructions,
TxFailure,
TxCompileErr,
TxDeserializationError,
QvnTxSendFailure,
InvalidInstructionError,
InvalidChain,
AnchorParse,
AnchorParseError,
EvmError,
IpfsParseError,
IpfsNetworkError,
HeartbeatRoutineFailure,
EventListenerRoutineFailure,
DecryptError,
ParseError,
MrEnclaveMismatch,
FunctionResultIxIncorrectTargetChain,
InvalidSignature,
SolanaBlockhashError,
SolanaSignError(ParentError, String),
FunctionResultIxMissingDiscriminator,
FunctionResultError(&'static str),
FunctionResultIxError(&'static str),
FunctionResultFailoverError(u8, ParentError),
FunctionResultNonRetryableError(ParentError),
AccountNotFound,
}
impl fmt::Display for SbError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SbError::EnvVariableMissing(message) => {
write!(f, "Env variable missing: {}", message.as_str())
}
SbError::Message(message) => write!(f, "error: {}", message),
SbError::CustomMessage(message) => write!(f, "error: {}", message.as_str()),
SbError::CustomError {
message, source, ..
} => write!(f, "error: {} - {:?}", message.as_str(), source),
SbError::FunctionResultError(message) => {
write!(f, "error: FunctionResultError - {}", message)
}
SbError::FunctionResultIxError(message) => {
write!(f, "error: FunctionResultIxError - {}", message)
}
SbError::FunctionResultFailoverError(code, source) => {
write!(
f,
"error: FunctionResultFailoverError ({}) - {:?}",
code, source
)
}
SbError::FunctionResultNonRetryableError(source) => {
write!(f, "error: FunctionResultNonRetryableError - {:?}", source)
}
_ => write!(f, "{:#?}", self),
}
}
}
impl From<&str> for SbError {
fn from(error: &str) -> Self {
SbError::CustomMessage(error.to_string())
}
}
impl From<String> for SbError {
fn from(error: String) -> Self {
SbError::CustomMessage(error)
}
}
impl From<hex::FromHexError> for SbError {
fn from(error: hex::FromHexError) -> Self {
SbError::CustomError {
message: "hex error".to_string(),
source: Arc::new(error),
}
}
}
impl StdError for SbError {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
SbError::CustomError { source, .. } => Some(source.as_ref()), SbError::ContainerError(source) => Some(source.as_ref()),
SbError::ContainerStartError(source) => Some(source.as_ref()),
SbError::SolanaSignError(source, ..) => Some(source.as_ref()),
SbError::FunctionResultFailoverError(_code, source, ..) => Some(source.as_ref()),
SbError::FunctionResultNonRetryableError(source, ..) => Some(source.as_ref()),
_ => None,
}
}
}
impl From<SerdeJsonError> for SbError {
fn from(error: SerdeJsonError) -> Self {
SbError::CustomError {
message: "serde_json error".to_string(),
source: Arc::new(error),
}
}
}
impl From<std::io::Error> for SbError {
fn from(val: std::io::Error) -> Self {
SbError::IoError(std::sync::Arc::new(val))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_generic() {
let error = SbError::Generic;
assert_eq!(format!("{}", error), "Generic");
}
#[test]
fn display_custom_message() {
let error = SbError::CustomMessage("my custom message".to_string());
assert_eq!(format!("{}", error), "error: my custom message");
}
#[test]
fn display_env_variable_missing() {
let error = SbError::EnvVariableMissing("MY_ENV_VAR".to_string());
assert_eq!(format!("{}", error), "Env variable missing: MY_ENV_VAR");
}
#[test]
fn from_str() {
let error: SbError = "my custom message".into();
assert_eq!(format!("{}", error), "error: my custom message");
}
#[test]
fn from_hex_error() {
let hex_error = hex::FromHexError::OddLength;
let error: SbError = hex_error.into();
assert_eq!(format!("{}", error), "error: hex error - OddLength");
}
#[test]
fn from_serde_json_error() {
let json = "\"";
let serde_json_error = serde_json::from_str::<serde_json::Value>(json).unwrap_err();
let error: SbError = serde_json_error.into();
assert!(format!("{}", error).starts_with("error: serde_json error - "));
}
}