use ipnetwork::IpNetworkError;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Json;
use mac_address::MacParseError;
use serde_json::json;
use std::io;
use tracing::{error, warn};
use utoipa::ToSchema;
#[derive(Debug, thiserror::Error, ToSchema)]
pub enum Error {
#[error("json: {source}")]
Json {
#[from]
source: serde_json::Error,
},
#[error("buffer parse: {source}")]
ParseInt {
#[from]
source: std::num::ParseIntError,
},
#[error("string parse: {source}")]
IpParse {
#[from]
source: IpNetworkError,
},
#[error("mac parse: {source}")]
MacParse {
#[from]
source: MacParseError,
},
#[error("io: {source}")]
Io {
#[from]
source: io::Error,
},
#[error("No ip set for device but ping requested")]
NoIpOnPing,
}
impl IntoResponse for Error {
fn into_response(self) -> Response {
let (status, error_message) = match self {
Self::Json { source } => {
// !THIS REALLY SHOULD NOT HAPPEN!:
// Json file has to had been tampered with by an external force
error!("{source}");
(StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
}
Self::ParseInt { source } => {
// !THIS REALLY SHOULD NOT HAPPEN!:
// Mac Address `&str` can't be converted to hex, which should be impossible trough
// `MacAddress` type-check on device registration and edit
error!("{source}");
(StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
}
Self::Io { source } => {
if source.kind() == io::ErrorKind::NotFound {
warn!("unknown device requested");
(StatusCode::NOT_FOUND, "Requested device not found")
} else {
error!("{source}");
(StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
}
}
Self::MacParse { source } => {
warn!("{source}");
(
StatusCode::INTERNAL_SERVER_ERROR,
"The given MAC-Address couldn't be parsed",
)
}
Self::IpParse { source } => {
warn!("{source}");
(
StatusCode::INTERNAL_SERVER_ERROR,
"The given IP-Address couldn't be parsed",
)
}
Self::NoIpOnPing => {
warn!("Ping requested but no ip given");
(
StatusCode::BAD_REQUEST,
"No IP saved for device, ping can't be executed. Device may be started anyway",
)
}
};
let body = Json(json!({
"error": error_message,
}));
(status, body).into_response()
}
}