use crate::prelude::*;
use core::fmt;
#[cfg(feature = "use_backtrace")]
use backtrace::Backtrace;
use log::*;
use crate::policy::error::{ValidationError, ValidationErrorKind};
#[derive(Clone)]
pub struct Status {
code: Code,
message: String,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Code {
Ok = 0,
InvalidArgument = 3,
FailedPrecondition = 9,
Internal = 13,
Temporary = 14,
}
impl Status {
pub fn new(code: Code, message: impl Into<String>) -> Self {
Status { code, message: message.into() }
}
pub fn code(&self) -> Code {
self.code
}
pub fn message(&self) -> &str {
&self.message
}
pub fn invalid_argument(message: impl Into<String>) -> Status {
Self::new(Code::InvalidArgument, message)
}
pub fn failed_precondition(message: impl Into<String>) -> Status {
Self::new(Code::FailedPrecondition, message)
}
pub fn internal(message: impl Into<String>) -> Status {
Self::new(Code::Internal, message)
}
pub fn temporary(message: impl Into<String>) -> Status {
Self::new(Code::Temporary, message)
}
}
impl fmt::Debug for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut builder = f.debug_struct("Status");
builder.field("code", &self.code);
if !self.message.is_empty() {
builder.field("message", &self.message);
}
builder.finish()
}
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "status: {:?}, message: {:?}", self.code(), self.message())
}
}
#[cfg(feature = "grpc")]
impl std::error::Error for Status {}
#[cfg(feature = "grpc")]
use core::convert::TryInto;
#[cfg(feature = "grpc")]
impl From<Status> for tonic::Status {
fn from(s: Status) -> Self {
let code = s.code() as i32;
tonic::Status::new(code.try_into().unwrap(), s.message())
}
}
pub fn invalid_argument(msg: impl Into<String>) -> Status {
let s = msg.into();
error!("INVALID ARGUMENT: {}", &s);
#[cfg(feature = "use_backtrace")]
error!("BACKTRACE:\n{:?}", Backtrace::new());
Status::invalid_argument(s)
}
pub(crate) fn internal_error(msg: impl Into<String>) -> Status {
let s = msg.into();
error!("INTERNAL ERROR: {}", &s);
#[cfg(feature = "use_backtrace")]
error!("BACKTRACE:\n{:?}", Backtrace::new());
Status::internal(s)
}
#[allow(unused)]
pub(crate) fn failed_precondition(msg: impl Into<String>) -> Status {
let s = msg.into();
error!("FAILED PRECONDITION: {}", &s);
Status::failed_precondition(s)
}
impl From<ValidationError> for Status {
fn from(ve: ValidationError) -> Self {
let res = match ve.kind {
ValidationErrorKind::TemporaryPolicy(ref s) => {
warn!("TEMPORARY POLICY ERROR: {}", s);
#[cfg(feature = "use_backtrace")]
warn!("BACKTRACE:\n{:?}", &ve.resolved_backtrace());
Status::temporary(s)
}
_ => {
let s: String = ve.clone().into();
error!("FAILED PRECONDITION: {}", &s);
#[cfg(feature = "use_backtrace")]
error!("BACKTRACE:\n{:?}", &ve.resolved_backtrace());
Status::failed_precondition(s)
}
};
res
}
}