use crate::Response;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("hyper error {0:?}")]
Hyper(#[from] hyper::Error),
#[error("http error {0:?}")]
HTTP(#[from] hyper::http::Error),
#[error("json error {0:?}")]
Json(#[from] serde_json::Error),
#[error("IO error {0:?}")]
IO(#[from] std::io::Error),
#[error("any error {0:?}")]
Any(#[from] anyhow::Error),
#[error("query error {0:?}")]
Urlencoded(#[from] serde_urlencoded::de::Error),
#[error("addr parse error {0:?}")]
AddrParse(#[from] std::net::AddrParseError),
#[error("InvalidStatusCode {0:?}")]
InvalidStatusCode(#[from] hyper::http::status::InvalidStatusCode),
#[error("missing url param {name:?}")]
MissingParam { name: String },
#[error("invalid param {name:?} as {expected:?}, {err:?}")]
InvalidParam {
name: String,
expected: &'static str,
err: String,
},
#[error("error msg {msg:?}")]
Message { msg: String },
#[error("session error {0:?}")]
Session(#[from] crate::session::SessionError),
}
pub fn missing_param(name: &str) -> Error {
Error::MissingParam {
name: name.to_string(),
}
}
pub fn error_msg(msg: &str) -> Error {
Error::Message {
msg: msg.to_string(),
}
}
pub fn invalid_param(
name: impl ToString,
expected: &'static str,
err: impl std::error::Error,
) -> Error {
Error::InvalidParam {
name: name.to_string(),
expected,
err: err.to_string(),
}
}
impl From<Error> for Response {
fn from(err: Error) -> Self {
Response::with_status(500, err.to_string()).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_missing_param() {
let err = missing_param("user_id");
assert!(matches!(err, Error::MissingParam { .. }));
if let Error::MissingParam { name } = err {
assert_eq!(name, "user_id");
}
}
#[test]
fn test_error_msg() {
let err = error_msg("test message");
assert!(matches!(err, Error::Message { .. }));
if let Error::Message { msg } = err {
assert_eq!(msg, "test message");
}
}
#[test]
fn test_invalid_param() {
use std::num::ParseIntError;
let parse_err: ParseIntError = "invalid digit".parse::<u32>().unwrap_err();
let err = invalid_param("age", "u32", parse_err);
assert!(matches!(err, Error::InvalidParam { .. }));
if let Error::InvalidParam {
name,
expected,
err: err_msg,
} = err
{
assert_eq!(name, "age");
assert_eq!(expected, "u32");
assert!(err_msg.contains("invalid"));
}
}
#[test]
fn test_error_display() {
let err = missing_param("id");
let display = format!("{}", err);
assert!(display.contains("missing url param"));
assert!(display.contains("id"));
}
}