zerolog 0.3.0

Simple low overhead easy to disable logging
Documentation
use std::{fmt::Display, str::FromStr};

use serde::{de::Visitor, Deserialize, Serialize};

#[derive(PartialEq, Eq, Serialize, Clone, Copy, Debug, PartialOrd, Ord)]
pub enum LogLevel {
    Trace,
    Debug,
    Info,
    Warn,
    Error,
}

impl Display for LogLevel {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Trace => write!(f, "trace"),
            Self::Debug => write!(f, "debug"),
            Self::Info =>  write!(f, "info"),
            Self::Warn =>  write!(f, "warn"),
            Self::Error => write!(f, "error"),
        }
    }
}

impl<'de> Deserialize<'de> for LogLevel {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
        deserializer.deserialize_str(LogLevelVisitor)
    }
}

struct LogLevelVisitor;

impl<'de> Visitor<'de> for LogLevelVisitor {
    type Value = LogLevel;
    
    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> where E: serde::de::Error {
        self.visit_str(&v)
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error {
        LogLevel::from_str(v).map_err(|_| E::unknown_variant(v, &["trace", "debug", "info", "warn", "error"]))
    }

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "one of [trace, debug, info, warn, error]")
    }
}

#[derive(Debug)]
pub struct LogLevelParseError(pub String);

impl std::fmt::Display for LogLevelParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl std::error::Error for LogLevelParseError {
}

impl FromStr for LogLevel {
    type Err = LogLevelParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.eq_ignore_ascii_case("trace") {
            Ok(LogLevel::Trace)
        }
        else if s.eq_ignore_ascii_case("debug") {
            Ok(LogLevel::Debug)
        }
        else if s.eq_ignore_ascii_case("info") {
            Ok(LogLevel::Info)
        }
        else if s.eq_ignore_ascii_case("warn") {
            Ok(LogLevel::Warn)
        }
        else if s.eq_ignore_ascii_case("error") {
            Ok(LogLevel::Error)
        } else {
            Err(LogLevelParseError(format!("unknown level: {:?}", s)))
        }
    }
}