1use crate::facility::Facility;
use crate::log_value::LogValue;
use crate::util::UtilTryInto;
use core::fmt::{Display, Formatter};
use tracing::{Level as TracingLevel, Level};
pub enum SeverityError {
ConversionError(ConversionError),
}
pub enum ConversionError {
IntegerOutOfBounds,
FloatOutOfBounds,
UnableToConvertBool,
StringDoesNotMatchValidSeverity,
UnableToConvertTimestamp,
UnableToConvertSeverity,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Severity {
Trace = 8,
Debug = 7,
Informational = 6,
Notice = 5,
Warning = 4,
Error = 3,
Critical = 2,
Alert = 1,
Emergency = 0,
}
impl Severity {
pub fn to_level(&self, facility: Option<&Facility>) -> u32 {
let facility_u32 = u32::from(facility.unwrap_or(&Facility::LocalUse7));
let severity_u32 = u32::from(self);
facility_u32 | severity_u32
}
}
impl Display for Severity {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Severity::Trace => write!(f, "Trace"),
Severity::Debug => write!(f, "Debug"),
Severity::Informational => write!(f, "Informational"),
Severity::Notice => write!(f, "Notice"),
Severity::Warning => write!(f, "Warning"),
Severity::Error => write!(f, "Error"),
Severity::Critical => write!(f, "Critical"),
Severity::Alert => write!(f, "Alert"),
Severity::Emergency => write!(f, "Emergency"),
}
}
}
impl From<Severity> for u32 {
fn from(s: Severity) -> Self {
Self::from(&s)
}
}
impl From<&Severity> for u32 {
fn from(s: &Severity) -> Self {
match s {
Severity::Trace => 8,
Severity::Debug => 7,
Severity::Informational => 6,
Severity::Notice => 5,
Severity::Warning => 4,
Severity::Error => 3,
Severity::Critical => 2,
Severity::Alert => 1,
Severity::Emergency => 0,
}
}
}
impl From<Severity> for TracingLevel {
fn from(t: Severity) -> Self {
match t {
Severity::Trace => TracingLevel::TRACE,
Severity::Debug => TracingLevel::DEBUG,
Severity::Informational => TracingLevel::INFO,
Severity::Notice => TracingLevel::WARN,
Severity::Warning => TracingLevel::WARN,
Severity::Error => TracingLevel::ERROR,
Severity::Critical => TracingLevel::ERROR,
Severity::Alert => TracingLevel::ERROR,
Severity::Emergency => TracingLevel::ERROR,
}
}
}
impl From<TracingLevel> for Severity {
fn from(t: TracingLevel) -> Self {
match t.as_str() {
"TRACE" => Severity::Trace,
"DEBUG" => Severity::Debug,
"INFO" => Severity::Informational,
"WARN" => Severity::Warning,
"ERROR" => Severity::Error,
_ => Severity::Error,
}
}
}
impl TryFrom<&str> for Severity {
type Error = SeverityError;
fn try_from(u: &str) -> Result<Self, <Severity as TryFrom<&str>>::Error> {
match u {
"debug" => Ok(Severity::Debug),
"informational" => Ok(Severity::Informational),
"notice" => Ok(Severity::Notice),
"warning" => Ok(Severity::Warning),
"error" => Ok(Severity::Error),
"critical" => Ok(Severity::Critical),
"alert" => Ok(Severity::Alert),
"emergency" => Ok(Severity::Emergency),
_ => Err(SeverityError::ConversionError(
ConversionError::StringDoesNotMatchValidSeverity,
)),
}
}
}
impl TryFrom<i64> for Severity {
type Error = SeverityError;
fn try_from(i: i64) -> Result<Self, <Severity as TryFrom<LogValue>>::Error> {
match i {
8 => Ok(Severity::Trace),
7 => Ok(Severity::Debug),
6 => Ok(Severity::Informational),
5 => Ok(Severity::Notice),
4 => Ok(Severity::Warning),
3 => Ok(Severity::Error),
2 => Ok(Severity::Critical),
1 => Ok(Severity::Alert),
0 => Ok(Severity::Emergency),
_ => Err(SeverityError::ConversionError(
ConversionError::IntegerOutOfBounds,
)),
}
}
}
impl TryFrom<u64> for Severity {
type Error = SeverityError;
fn try_from(u: u64) -> Result<Self, <Severity as TryFrom<LogValue>>::Error> {
u.util_try_into()
.map_err(|_| SeverityError::ConversionError(ConversionError::FloatOutOfBounds))
.and_then(|i: i64| Severity::try_from(i))
}
}
impl TryFrom<f64> for Severity {
type Error = SeverityError;
fn try_from(f: f64) -> Result<Self, <Severity as TryFrom<LogValue>>::Error> {
f.util_try_into()
.map_err(|_| SeverityError::ConversionError(ConversionError::FloatOutOfBounds))
.and_then(|i: i64| Severity::try_from(i))
}
}
impl TryFrom<LogValue> for Severity {
type Error = SeverityError;
fn try_from(value: LogValue) -> Result<Self, <Severity as TryFrom<LogValue>>::Error> {
Self::try_from(&value)
}
}
impl TryFrom<&LogValue> for Severity {
type Error = SeverityError;
fn try_from(value: &LogValue) -> Result<Self, <Severity as TryFrom<LogValue>>::Error> {
match value {
LogValue::I64(i) => Severity::try_from(*i),
LogValue::U64(u) => Severity::try_from(*u),
LogValue::F64(f) => Severity::try_from(*f),
LogValue::Bool(_) => Err(SeverityError::ConversionError(
ConversionError::UnableToConvertBool,
)),
LogValue::String(s) => Severity::try_from(s.as_str()),
LogValue::Debug(s) => Severity::try_from(s.as_str()),
LogValue::TimeStamp(_) => Err(SeverityError::ConversionError(
ConversionError::UnableToConvertTimestamp,
)),
LogValue::Severity(t) => Err(SeverityError::ConversionError(
ConversionError::UnableToConvertSeverity,
)),
}
}
}
impl From<&tracing::Level> for Severity {
fn from(t: &tracing::Level) -> Self {
match t {
&tracing::Level::TRACE => Severity::Trace,
&tracing::Level::ERROR => Severity::Error,
&tracing::Level::DEBUG => Severity::Debug,
&tracing::Level::WARN => Severity::Warning,
&tracing::Level::INFO => Severity::Informational,
}
}
}