golgi/src/error.rs

137 lines
4.4 KiB
Rust

//! Custom error type.
use std::io::Error as IoError;
use std::str::Utf8Error;
use base64::DecodeError;
use kuska_handshake::async_std::Error as HandshakeError;
use kuska_ssb::api::Error as ApiError;
use kuska_ssb::feed::Error as FeedError;
use kuska_ssb::rpc::Error as RpcError;
use serde_json::Error as JsonError;
/// A custom error type encapsulating all possible errors for this library.
/// `From` implementations are provided for external error types, allowing
/// the `?` operator to be used on functions which return `Result<_, GolgiError>`.
#[derive(Debug)]
pub enum GolgiError {
/// Failed to decode base64.
DecodeBase64(DecodeError),
/// IO error with context.
Io {
/// The underlying IO error.
source: IoError,
/// Description of the error context.
context: String,
},
/// Scuttlebutt secret handshake error.
Handshake(HandshakeError),
/// Kuska SSB API error.
Api(ApiError),
/// Kuska SSB feed error.
Feed(FeedError),
/// Kuska SSB RPC error.
Rpc(RpcError),
/// Go-sbot error.
Sbot(String),
/// SSB sigil-link error.
SigilLink(String),
/// JSON serialization or deserialization error.
SerdeJson(JsonError),
/// Error decoding typed SSB message from content.
ContentType(String),
/// Error decoding UTF8 string from bytes
Utf8Parse {
/// The underlying parse error.
source: Utf8Error,
},
}
impl std::error::Error for GolgiError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
GolgiError::DecodeBase64(ref err) => Some(err),
GolgiError::Io { ref source, .. } => Some(source),
GolgiError::Handshake(_) => None,
GolgiError::Api(ref err) => Some(err),
GolgiError::Feed(ref err) => Some(err),
GolgiError::Rpc(ref err) => Some(err),
GolgiError::Sbot(_) => None,
GolgiError::SigilLink(_) => None,
GolgiError::SerdeJson(ref err) => Some(err),
GolgiError::ContentType(_) => None,
GolgiError::Utf8Parse { ref source } => Some(source),
}
}
}
impl std::fmt::Display for GolgiError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
// TODO: add context (what were we trying to decode?)
GolgiError::DecodeBase64(_) => write!(f, "Failed to decode base64"),
GolgiError::Io { ref context, .. } => write!(f, "IO error: {}", context),
GolgiError::Handshake(ref err) => write!(f, "Handshake failure: {}", err),
GolgiError::Api(ref err) => write!(f, "SSB API failure: {}", err),
GolgiError::Feed(ref err) => write!(f, "SSB feed error: {}", err),
// TODO: improve this variant with a context message
// then have the core display msg be: "SSB RPC error: {}", context
GolgiError::Rpc(ref err) => write!(f, "SSB RPC failure: {}", err),
GolgiError::Sbot(ref err) => write!(f, "Sbot encountered an error: {}", err),
GolgiError::SigilLink(ref context) => write!(f, "SSB blob ID error: {}", context),
GolgiError::SerdeJson(_) => write!(f, "Failed to serialize JSON slice"),
//GolgiError::WhoAmI(ref err) => write!(f, "{}", err),
GolgiError::ContentType(ref err) => write!(
f,
"Failed to decode typed message from SSB message content: {}",
err
),
GolgiError::Utf8Parse { source } => {
write!(f, "Failed to deserialize UTF8 from bytes: {}", source)
}
}
}
}
impl From<DecodeError> for GolgiError {
fn from(err: DecodeError) -> Self {
GolgiError::DecodeBase64(err)
}
}
impl From<HandshakeError> for GolgiError {
fn from(err: HandshakeError) -> Self {
GolgiError::Handshake(err)
}
}
impl From<ApiError> for GolgiError {
fn from(err: ApiError) -> Self {
GolgiError::Api(err)
}
}
impl From<FeedError> for GolgiError {
fn from(err: FeedError) -> Self {
GolgiError::Feed(err)
}
}
impl From<RpcError> for GolgiError {
fn from(err: RpcError) -> Self {
GolgiError::Rpc(err)
}
}
impl From<JsonError> for GolgiError {
fn from(err: JsonError) -> Self {
GolgiError::SerdeJson(err)
}
}
impl From<Utf8Error> for GolgiError {
fn from(err: Utf8Error) -> Self {
GolgiError::Utf8Parse { source: err }
}
}