use thiserror::Error;
use crate::{error::Result, proto::CommandStatus};
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("command: {0}")]
CommandError(#[from] CommandError),
#[error("storage: {0}")]
StorageError(#[from] StorageError),
#[error("application: {0}")]
ApplicationError(#[from] ApplicationError),
#[error("virtual display: {0}")]
VirtualDisplayError(#[from] VirtualDisplayError),
#[error("gpio: {0}")]
GPIOError(#[from] GPIOError),
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum CommandError {
#[error("unknown error (ERROR)")]
Unknown,
#[error("decode error (ERROR_DECODE)")]
Decode,
#[error("not implemented (ERROR_NOT_IMPLEMENTED)")]
NotImplemented,
#[error("busy (ERROR_BUSY)")]
Busy,
#[error("continuous command interrupted (ERROR_CONTINUOUS_COMMAND_INTERRUPTED)")]
ContinuousCommandInterrupted,
#[error("invalid RPC parameters (ERROR_INVALID_PARAMETERS)")]
InvalidParameters,
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum StorageError {
#[error("filesystem is not ready for use (ERROR_STORAGE_NOT_READY)")]
NotReady,
#[error("file/dir already exists (ERROR_STORAGE_EXIST)")]
AlreadyExists,
#[error("file/dir not found (ERROR_STORAGE_NOT_EXIST)")]
NotFound,
#[error("invalid storage parameter (ERROR_STORAGE_INVALID_PARAMETER)")]
InvalidParameter,
#[error("permission denied (ERROR_STORAGE_DENIED)")]
PermissionDenied,
#[error("invalid name/path (ERROR_STORAGE_INVALID_NAME)")]
InvalidName,
#[error("internal error (ERROR_STORAGE_INTERNAL)")]
Internal,
#[error("not implemented (ERROR_STORAGE_NOT_IMPLEMENTED)")]
NotImplemented,
#[error("already open (ERROR_STORAGE_ALREADY_OPEN)")]
AlreadyOpen,
#[error("directory not empty (ERROR_STORAGE_DIR_NOT_EMPTY)")]
DirectoryNotEmpty,
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum ApplicationError {
#[error("unable to start app - internal (ERROR_APP_CANT_START)")]
CannotStart,
#[error("system locked, another app is already running (ERROR_APP_SYSTEM_LOCKED)")]
SystemLocked,
#[error("rpc is unavailable for app (ERROR_APP_NOT_RUNNING)")]
RpcUnavailable,
#[error("command execution error (ERROR_APP_CMD_ERROR)")]
CommandExecution,
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum VirtualDisplayError {
#[error("session already started (ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED)")]
AlreadyStarted,
#[error("session not started (ERROR_VIRTUAL_DISPLAY_NOT_STARTED)")]
NotStarted,
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum GPIOError {
#[error("incorrect pin mode (ERROR_GPIO_MODE_INCORRECT)")]
IncorrectMode,
#[error("unknown pin mode (ERROR_GPIO_UNKNOWN_PIN_MODE)")]
UnknownMode,
}
impl CommandStatus {
pub fn into_result<T>(self, value: T) -> Result<T> {
let result: std::result::Result<T, Error> = match self {
CommandStatus::Ok => Ok(value),
CommandStatus::Error => Err(CommandError::Unknown.into()),
CommandStatus::ErrorDecode => Err(CommandError::Decode.into()),
CommandStatus::ErrorNotImplemented => Err(CommandError::NotImplemented.into()),
CommandStatus::ErrorBusy => Err(CommandError::Busy.into()),
CommandStatus::ErrorContinuousCommandInterrupted => {
Err(CommandError::ContinuousCommandInterrupted.into())
}
CommandStatus::ErrorInvalidParameters => Err(CommandError::InvalidParameters.into()),
CommandStatus::ErrorStorageNotReady => Err(StorageError::NotReady.into()),
CommandStatus::ErrorStorageExist => Err(StorageError::AlreadyExists.into()),
CommandStatus::ErrorStorageNotExist => Err(StorageError::NotFound.into()),
CommandStatus::ErrorStorageInvalidParameter => {
Err(StorageError::InvalidParameter.into())
}
CommandStatus::ErrorStorageDenied => Err(StorageError::PermissionDenied.into()),
CommandStatus::ErrorStorageInvalidName => Err(StorageError::InvalidName.into()),
CommandStatus::ErrorStorageInternal => Err(StorageError::Internal.into()),
CommandStatus::ErrorStorageNotImplemented => Err(StorageError::NotImplemented.into()),
CommandStatus::ErrorStorageAlreadyOpen => Err(StorageError::AlreadyOpen.into()),
CommandStatus::ErrorStorageDirNotEmpty => Err(StorageError::DirectoryNotEmpty.into()),
CommandStatus::ErrorAppCantStart => Err(ApplicationError::CannotStart.into()),
CommandStatus::ErrorAppSystemLocked => Err(ApplicationError::SystemLocked.into()),
CommandStatus::ErrorAppNotRunning => Err(ApplicationError::RpcUnavailable.into()),
CommandStatus::ErrorAppCmdError => Err(ApplicationError::CommandExecution.into()),
CommandStatus::ErrorVirtualDisplayAlreadyStarted => {
Err(VirtualDisplayError::AlreadyStarted.into())
}
CommandStatus::ErrorVirtualDisplayNotStarted => {
Err(VirtualDisplayError::NotStarted.into())
}
CommandStatus::ErrorGpioModeIncorrect => Err(GPIOError::IncorrectMode.into()),
CommandStatus::ErrorGpioUnknownPinMode => Err(GPIOError::UnknownMode.into()),
};
result.map_err(Into::into)
}
}