use crate::cfg_serde;
use std::fmt;
use tracing::{Event, Level};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct Tag {
prefix: Option<&'static str>,
suffix: &'static str,
icon: char,
}
impl Tag {
pub fn builder() -> Builder<(), ()> {
Builder {
prefix: None,
suffix: (),
icon: (),
}
}
pub const fn prefix(&self) -> Option<&'static str> {
self.prefix
}
pub const fn suffix(&self) -> &'static str {
self.suffix
}
pub const fn icon(&self) -> char {
self.icon
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Builder<S, I> {
prefix: Option<&'static str>,
suffix: S,
icon: I,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Suffix(&'static str);
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Icon(char);
impl<S, I> Builder<S, I> {
pub fn prefix(self, prefix: &'static str) -> Builder<S, I> {
Builder {
prefix: Some(prefix),
..self
}
}
pub fn suffix(self, suffix: &'static str) -> Builder<Suffix, I> {
Builder {
prefix: self.prefix,
suffix: Suffix(suffix),
icon: self.icon,
}
}
pub fn icon(self, icon: char) -> Builder<S, Icon> {
Builder {
prefix: self.prefix,
suffix: self.suffix,
icon: Icon(icon),
}
}
pub fn level(self, level: Level) -> Builder<Suffix, Icon> {
let (suffix, icon) = match level {
Level::TRACE => ("trace", '📍'),
Level::DEBUG => ("debug", '🐛'),
Level::INFO => ("info", 'i'),
Level::WARN => ("warn", '🚧'),
Level::ERROR => ("error", '🚨'),
};
Builder {
prefix: self.prefix,
suffix: Suffix(suffix),
icon: Icon(icon),
}
}
}
impl Builder<Suffix, Icon> {
pub fn build(self) -> Tag {
Tag {
prefix: self.prefix,
suffix: self.suffix.0,
icon: self.icon.0,
}
}
}
impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(prefix) = self.prefix {
write!(f, "{}.{}", prefix, self.suffix)
} else {
self.suffix.fmt(f)
}
}
}
impl From<Level> for Tag {
fn from(level: Level) -> Self {
Tag::builder().level(level).build()
}
}
cfg_serde! {
use serde::{Serialize, Serializer};
impl Serialize for Tag {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&self.to_string())
}
}
}
pub trait TagParser: 'static {
fn parse(&self, event: &Event) -> Option<Tag>;
}
#[derive(Clone, Debug)]
pub struct NoTag;
impl TagParser for NoTag {
fn parse(&self, _event: &Event) -> Option<Tag> {
None
}
}
impl<F> TagParser for F
where
F: 'static + Fn(&Event) -> Option<Tag>,
{
fn parse(&self, event: &Event) -> Option<Tag> {
self(event)
}
}