use crate::{connector, device, serialization, session};
use anomaly::{BoxError, Context};
use std::io;
use thiserror::Error;
pub type Error = crate::Error<ErrorKind>;
#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
pub enum ErrorKind {
#[error("authentication failed")]
AuthenticationError,
#[error("session closed")]
ClosedSessionError,
#[error("connector error")]
ConnectorError,
#[error("couldn't create session")]
CreateFailed,
#[error("HSM error")]
DeviceError,
#[error("protocol error")]
ProtocolError,
#[error("HSM response error")]
ResponseError,
}
impl Error {
pub fn device_error(&self) -> Option<device::ErrorKind> {
use std::error::Error;
if let Some(session_err) = self.source()?.downcast_ref::<session::Error>() {
session_err.source()?.downcast_ref().cloned()
} else {
None
}
}
}
impl ErrorKind {
pub fn context(self, source: impl Into<BoxError>) -> Context<ErrorKind> {
Context::new(self, Some(source.into()))
}
}
impl From<connector::Error> for Error {
fn from(err: connector::Error) -> Self {
ErrorKind::ConnectorError.context(err).into()
}
}
impl From<session::Error> for Error {
fn from(err: session::Error) -> Self {
let kind = match err.kind() {
session::ErrorKind::AuthenticationError => ErrorKind::AuthenticationError,
session::ErrorKind::ClosedError => ErrorKind::ClosedSessionError,
session::ErrorKind::CreateFailed => ErrorKind::CreateFailed,
session::ErrorKind::DeviceError => ErrorKind::DeviceError,
session::ErrorKind::ProtocolError
| session::ErrorKind::CommandLimitExceeded
| session::ErrorKind::MismatchError
| session::ErrorKind::VerifyFailed => ErrorKind::ProtocolError,
session::ErrorKind::ResponseError => ErrorKind::ResponseError,
};
kind.context(err).into()
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
ErrorKind::ProtocolError.context(err).into()
}
}
impl From<serialization::Error> for Error {
fn from(err: serialization::Error) -> Self {
ErrorKind::ProtocolError.context(err).into()
}
}
impl From<Error> for signature::Error {
fn from(client_error: Error) -> signature::Error {
signature::Error::from_source(client_error)
}
}