use std::error::Error;
use displaydoc::Display;
use massa_consensus_exports::error::ConsensusError;
use massa_execution_exports::ExecutionError;
use massa_hash::MassaHashError;
use massa_models::error::ModelsError;
use massa_protocol_exports::ProtocolError;
use massa_signature::MassaSignatureError;
use massa_time::TimeError;
use massa_versioning::versioning_factory::FactoryError;
use massa_wallet::WalletError;
use tracing::error;
#[non_exhaustive]
#[derive(Display, thiserror::Error, Debug)]
pub enum GrpcError {
MassaHashError(#[from] MassaHashError),
MassaSignatureError(#[from] MassaSignatureError),
ConsensusError(#[from] ConsensusError),
ExecutionError(#[from] ExecutionError),
ProtocolError(#[from] ProtocolError),
ReflectionError(#[from] tonic_reflection::server::Error),
ModelsError(#[from] ModelsError),
TimeError(#[from] TimeError),
FactoryError(#[from] FactoryError),
WalletError(#[from] WalletError),
InternalServerError(String),
InvalidArgument(String),
Unimplemented(String),
}
impl From<GrpcError> for tonic::Status {
fn from(error: GrpcError) -> Self {
error!("{}", error);
match error {
GrpcError::MassaHashError(e) => tonic::Status::internal(e.to_string()),
GrpcError::MassaSignatureError(e) => tonic::Status::internal(e.to_string()),
GrpcError::ConsensusError(e) => tonic::Status::internal(e.to_string()),
GrpcError::ExecutionError(e) => tonic::Status::internal(e.to_string()),
GrpcError::ProtocolError(e) => tonic::Status::internal(e.to_string()),
GrpcError::ModelsError(e) => tonic::Status::internal(e.to_string()),
GrpcError::TimeError(e) => tonic::Status::internal(e.to_string()),
GrpcError::FactoryError(e) => tonic::Status::internal(e.to_string()),
GrpcError::WalletError(e) => tonic::Status::internal(e.to_string()),
GrpcError::InternalServerError(e) => tonic::Status::internal(e),
GrpcError::ReflectionError(e) => tonic::Status::internal(e.to_string()),
GrpcError::InvalidArgument(e) => tonic::Status::invalid_argument(e),
GrpcError::Unimplemented(e) => tonic::Status::unimplemented(e),
}
}
}
pub fn match_for_io_error(err_status: &tonic::Status) -> Option<&std::io::Error> {
let mut err: &(dyn Error + 'static) = err_status;
loop {
if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
return Some(io_err);
}
if let Some(h2_err) = err.downcast_ref::<h2::Error>() {
if let Some(io_err) = h2_err.get_io() {
return Some(io_err);
}
}
err = match err.source() {
Some(err) => err,
None => return None,
};
}
}