Change ErrorCategory to ErrorType

This commit is contained in:
mpostma 2020-05-25 19:11:38 +02:00
parent 30fd24aa47
commit 0e20ac28e5
1 changed files with 61 additions and 128 deletions

View File

@ -7,8 +7,22 @@ pub trait ErrorCode: std::error::Error {
fn error_code(&self) -> Code;
}
enum ErrorCategory {
None = 0,
enum ErrorType {
InternalError,
InvalidRequest,
Authentication,
}
impl fmt::Display for ErrorType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ErrorType::*;
match self {
InternalError => write!(f, "internal_error"),
InvalidRequest => write!(f, "invalid_request"),
Authentication => write!(f, "authentication"),
}
}
}
pub enum Code {
@ -39,154 +53,73 @@ impl Code {
use Code::*;
match self {
BadParameter
| BadRequest
| CreateIndex
| InvalidIndexUid
| OpenIndex
| RetrieveDocument
| SearchDocuments => ErrCode::bad_request(false, false, ErrorCategory::None, 0),
DocumentNotFound
| IndexNotFound
| NotFound => ErrCode::not_found(false, false, ErrorCategory::None, 0),
InvalidToken
| MissingHeader => ErrCode::unauthorized(false, false, ErrorCategory::None, 0),
MissingAuthorizationHeader => ErrCode::forbidden(false, false, ErrorCategory::None, 0),
Internal => ErrCode::internal(false, false, ErrorCategory::None, 0),
Maintenance => ErrCode::service_unavailable(false, false, ErrorCategory::None, 0),
PayloadTooLarge => ErrCode::payload_too_large(false, false, ErrorCategory::None, 0),
UnsupportedMediaType => ErrCode::unsupported_media_type(false, false, ErrorCategory::None, 0),
_ => ErrCode::not_found(false, false, ErrorCategory::None, 0),
BadParameter => ErrCode::invalid("bad_parameter", StatusCode::BAD_REQUEST),
BadRequest => ErrCode::invalid("bad_request", StatusCode::BAD_REQUEST),
CreateIndex => ErrCode::invalid("create_index", StatusCode::BAD_REQUEST),
InvalidIndexUid => ErrCode::invalid("invalid_index_uid", StatusCode::BAD_REQUEST),
OpenIndex => ErrCode::invalid("open_index", StatusCode::BAD_REQUEST),
RetrieveDocument => ErrCode::invalid("retrieve_document", StatusCode::BAD_REQUEST),
SearchDocuments => ErrCode::invalid("search_document", StatusCode::BAD_REQUEST),
DocumentNotFound => ErrCode::invalid("document_not_found", StatusCode::BAD_REQUEST),
IndexNotFound => ErrCode::invalid("index_not_found", StatusCode::BAD_REQUEST),
NotFound => ErrCode::invalid("not_found", StatusCode::BAD_REQUEST),
InvalidToken => ErrCode::invalid("invalid_token", StatusCode::BAD_REQUEST),
MissingHeader => ErrCode::invalid("missing_header", StatusCode::BAD_REQUEST),
MissingAuthorizationHeader => ErrCode::invalid("missing_authorization_header", StatusCode::BAD_REQUEST),
Internal => ErrCode::invalid("internal", StatusCode::BAD_REQUEST),
Maintenance => ErrCode::invalid("maintenance", StatusCode::BAD_REQUEST),
PayloadTooLarge => ErrCode::invalid("payload_too_large", StatusCode::BAD_REQUEST),
UnsupportedMediaType => ErrCode::invalid("unsupported_media_type", StatusCode::BAD_REQUEST),
_ => ErrCode::invalid("other", StatusCode::BAD_REQUEST),
}
}
/// return the HTTP status code ascociated with the `Code`
pub fn http(&self) -> StatusCode {
self.err_code().http_code
self.err_code().status_code
}
/// returns internal error code, in the form:
/// `EPFCNN`
/// - E: plain letter "E", to mark an error code, future main introduce W for warning
/// - P: scope of the error, 0 for private, 1 for public. Private are error that make no sense
/// reporting to the user, they are internal errors, and there is nothing the user can do about
/// them. they are nonetheless returned, without a message, for assistance purpose.
/// - F: 0 or 1, report if the error is fatal.
/// - C: error category, number in 0-9, the category of the error. Categories are still to be determined, input is required.
/// - NN: The error number, two digits, within C.
pub fn internal(&self) -> String {
let ErrCode { public, fatal, category, code, .. } = self.err_code();
format!("E{}{}{}{}",
public as u16,
fatal as u16,
category as u16,
code)
/// return error name, used as error code
pub fn name(&self) -> String {
self.err_code().err_name.to_string()
}
}
impl fmt::Display for Code {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.internal().fmt(f)
/// return the error type
pub fn r#type(&self) -> String {
self.err_code().err_type.to_string()
}
}
/// Internal structure providing a convenient way to create error codes
struct ErrCode {
public: bool,
fatal: bool,
http_code: StatusCode,
category: ErrorCategory,
code: u16,
status_code: StatusCode,
err_type: ErrorType,
err_name: &'static str,
}
impl ErrCode {
fn new(
public: bool,
fatal: bool,
http_code: StatusCode,
category: ErrorCategory,
code: u16
) -> ErrCode {
fn authentication(err_name: &'static str, status_code: StatusCode) -> ErrCode {
ErrCode {
public,
fatal,
http_code,
category,
code,
status_code,
err_name,
err_type: ErrorType::Authentication,
}
}
pub fn internal(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::INTERNAL_SERVER_ERROR, category, code)
fn internal(err_name: &'static str, status_code: StatusCode) -> ErrCode {
ErrCode {
status_code,
err_name,
err_type: ErrorType::InternalError,
}
}
pub fn bad_request(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::BAD_REQUEST, category, code)
}
pub fn unsupported_media_type(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::UNSUPPORTED_MEDIA_TYPE, category, code)
}
pub fn payload_too_large(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::PAYLOAD_TOO_LARGE, category, code)
}
pub fn service_unavailable(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::SERVICE_UNAVAILABLE, category, code)
}
pub fn forbidden(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::FORBIDDEN, category, code)
}
pub fn unauthorized(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::UNAUTHORIZED, category, code)
}
pub fn not_found(
public: bool,
fatal: bool,
category: ErrorCategory,
code: u16
) -> ErrCode {
ErrCode::new(public, fatal, StatusCode::NOT_FOUND, category, code)
fn invalid(err_name: &'static str, status_code: StatusCode) -> ErrCode {
ErrCode {
status_code,
err_name,
err_type: ErrorType::InvalidRequest,
}
}
}