use thiserror::Error;
use crate::message::{Status, StatusCode};
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
Sftp(#[from] Status),
#[error(transparent)]
WireFormat(#[from] crate::wire::Error),
#[error(transparent)]
Ssh(russh::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
}
impl From<russh::Error> for Error {
fn from(value: russh::Error) -> Self {
match value {
russh::Error::IO(io) => Error::Io(io),
other => Error::Ssh(other),
}
}
}
impl From<crate::message::DecodeError> for Error {
fn from(value: crate::message::DecodeError) -> Self {
Self::WireFormat(value.inner)
}
}
impl From<Error> for std::io::Error {
fn from(value: Error) -> Self {
match value {
Error::Sftp(sftp) => {
let kind = match sftp.code {
StatusCode::Ok => std::io::ErrorKind::Other,
StatusCode::Eof => std::io::ErrorKind::UnexpectedEof,
StatusCode::NoSuchFile => std::io::ErrorKind::NotFound,
StatusCode::PermissionDenied => std::io::ErrorKind::PermissionDenied,
StatusCode::Failure => std::io::ErrorKind::Other,
StatusCode::BadMessage => std::io::ErrorKind::InvalidData,
StatusCode::NoConnection => std::io::ErrorKind::Other,
StatusCode::ConnectionLost => std::io::ErrorKind::Other,
StatusCode::OpUnsupported => std::io::ErrorKind::Unsupported,
};
Self::new(kind, sftp)
}
Error::WireFormat(wire) => std::io::Error::new(std::io::ErrorKind::Other, wire),
Error::Ssh(russh::Error::IO(io)) => io,
Error::Ssh(ssh) => std::io::Error::new(std::io::ErrorKind::Other, ssh),
Error::Io(io) => io,
}
}
}