use core::fmt;
use serde::{Deserialize, Serialize};
pub enum ConfigCheckIssue {
Warning(String),
Error(String),
}
#[derive(thiserror::Error, Debug, Serialize, Deserialize)]
pub enum Error {
#[error("app already exists")]
AppAlreadyExists,
#[error("Host already exists")]
HostAlreadyExists,
#[error("IO error: {0}")]
Io(String),
#[error("Failed: {0}")]
Failed(String),
#[error("Not implemented")]
NotImplemented,
#[error("Crypto engine error: {0}")]
Crypto(String),
#[error("Access denied: {0}")]
AccessDenied(String),
#[error("{0}")]
AccessDeniedMoreDataRequired(String),
#[error("Method not found: {0}")]
RpcMethodNotFound(String),
#[error("Invalid data: {0}")]
InvalidData(String),
#[error("Resource not found: {0}")]
NotFound(String),
#[error("Database error: {0}")]
Database(String),
#[error("Timeout")]
Timeout,
}
impl From<busrt::rpc::RpcError> for Error {
fn from(e: busrt::rpc::RpcError) -> Self {
let Some(data) = e.data().filter(|d| !d.is_empty()) else {
return Error::Failed("Bus error".to_string());
};
let Ok(e) = crate::gate::unpack(data) else {
return Error::Failed("Unreadable bus error".to_string());
};
e
}
}
impl From<Error> for busrt::rpc::RpcError {
fn from(e: Error) -> Self {
let Ok(data) = crate::gate::pack(&e) else {
return busrt::rpc::RpcError::internal(None);
};
busrt::rpc::RpcError::new(0, Some(data))
}
}
impl Error {
pub fn failed<S: fmt::Display>(msg: S) -> Self {
Error::Failed(msg.to_string())
}
pub fn invalid_data<S: fmt::Display>(msg: S) -> Self {
Error::InvalidData(msg.to_string())
}
pub fn access<S: fmt::Display>(msg: S) -> Self {
Error::AccessDenied(msg.to_string())
}
pub fn crypto<S: fmt::Display>(msg: S) -> Self {
Error::Crypto(msg.to_string())
}
pub fn io<S: fmt::Display>(msg: S) -> Self {
Error::Io(msg.to_string())
}
}
impl From<tokio::time::error::Elapsed> for Error {
fn from(_e: tokio::time::error::Elapsed) -> Self {
Error::Timeout
}
}
impl From<busrt::Error> for Error {
fn from(e: busrt::Error) -> Self {
Error::Io(e.to_string())
}
}
impl From<sqlx::Error> for Error {
fn from(e: sqlx::Error) -> Self {
Error::Database(e.to_string())
}
}
impl From<sqlite::Error> for Error {
fn from(e: sqlite::Error) -> Self {
Error::Database(e.to_string())
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::InvalidData(e.to_string())
}
}
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Self {
Error::InvalidData(e.to_string())
}
}
impl From<toml::ser::Error> for Error {
fn from(e: toml::ser::Error) -> Self {
Error::InvalidData(e.to_string())
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::Io(e.to_string())
}
}
impl From<tokio_rustls::rustls::Error> for Error {
fn from(e: tokio_rustls::rustls::Error) -> Self {
Error::Crypto(e.to_string())
}
}
impl From<tokio_rustls::rustls::pki_types::pem::Error> for Error {
fn from(e: tokio_rustls::rustls::pki_types::pem::Error) -> Self {
Error::Crypto(e.to_string())
}
}