tari_log4rs/encode/
mod.rs

1//! Encoders
2
3use derivative::Derivative;
4use log::Record;
5use std::{fmt, io};
6
7#[cfg(feature = "config_parsing")]
8use serde::de;
9#[cfg(feature = "config_parsing")]
10use serde_value::Value;
11#[cfg(feature = "config_parsing")]
12use std::collections::BTreeMap;
13
14#[cfg(feature = "config_parsing")]
15use crate::config::Deserializable;
16
17#[cfg(feature = "json_encoder")]
18pub mod json;
19#[cfg(feature = "pattern_encoder")]
20pub mod pattern;
21pub mod writer;
22
23#[allow(dead_code)]
24#[cfg(windows)]
25const NEWLINE: &'static str = "\r\n";
26
27#[allow(dead_code)]
28#[cfg(not(windows))]
29const NEWLINE: &str = "\n";
30
31/// A trait implemented by types that can serialize a `Record` into a
32/// `Write`r.
33///
34/// `Encode`rs are commonly used by `Append`ers to format a log record for
35/// output.
36pub trait Encode: fmt::Debug + Send + Sync + 'static {
37    /// Encodes the `Record` into bytes and writes them.
38    fn encode(&self, w: &mut dyn Write, record: &Record) -> anyhow::Result<()>;
39}
40
41#[cfg(feature = "config_parsing")]
42impl Deserializable for dyn Encode {
43    fn name() -> &'static str {
44        "encoder"
45    }
46}
47
48/// Configuration for an encoder.
49#[cfg(feature = "config_parsing")]
50#[derive(Clone, Eq, PartialEq, Hash, Debug)]
51pub struct EncoderConfig {
52    /// The encoder's kind.
53    pub kind: String,
54
55    /// The encoder's configuration.
56    pub config: Value,
57}
58
59#[cfg(feature = "config_parsing")]
60impl<'de> de::Deserialize<'de> for EncoderConfig {
61    fn deserialize<D>(d: D) -> Result<EncoderConfig, D::Error>
62    where
63        D: de::Deserializer<'de>,
64    {
65        let mut map = BTreeMap::<Value, Value>::deserialize(d)?;
66
67        let kind = match map.remove(&Value::String("kind".to_owned())) {
68            Some(kind) => kind.deserialize_into().map_err(|e| e.to_error())?,
69            None => "pattern".to_owned(),
70        };
71
72        Ok(EncoderConfig {
73            kind,
74            config: Value::Map(map),
75        })
76    }
77}
78
79/// A text or background color.
80#[allow(missing_docs)]
81#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
82pub enum Color {
83    Black,
84    Red,
85    Green,
86    Yellow,
87    Blue,
88    Magenta,
89    Cyan,
90    White,
91}
92
93/// The style applied to text output.
94///
95/// Any fields set to `None` will be set to their default format, as defined
96/// by the `Write`r.
97#[derive(Derivative)]
98#[derivative(Debug)]
99#[derive(Clone, Eq, PartialEq, Hash, Default)]
100pub struct Style {
101    /// The text (or foreground) color.
102    pub text: Option<Color>,
103    /// The background color.
104    pub background: Option<Color>,
105    /// True if the text should have increased intensity.
106    pub intense: Option<bool>,
107    #[derivative(Debug = "ignore")]
108    _p: (),
109}
110
111impl Style {
112    /// Returns a `Style` with all fields set to their defaults.
113    pub fn new() -> Style {
114        Style::default()
115    }
116
117    /// Sets the text color.
118    pub fn text(&mut self, text: Color) -> &mut Style {
119        self.text = Some(text);
120        self
121    }
122
123    /// Sets the background color.
124    pub fn background(&mut self, background: Color) -> &mut Style {
125        self.background = Some(background);
126        self
127    }
128
129    /// Sets the text intensity.
130    pub fn intense(&mut self, intense: bool) -> &mut Style {
131        self.intense = Some(intense);
132        self
133    }
134}
135
136/// A trait for types that an `Encode`r will write to.
137///
138/// It extends `std::io::Write` and adds some extra functionality.
139pub trait Write: io::Write {
140    /// Sets the output text style, if supported.
141    ///
142    /// `Write`rs should ignore any parts of the `Style` they do not support.
143    ///
144    /// The default implementation returns `Ok(())`. Implementations that do
145    /// not support styling should do this as well.
146    #[allow(unused_variables)]
147    fn set_style(&mut self, style: &Style) -> io::Result<()> {
148        Ok(())
149    }
150}
151
152impl<'a, W: Write + ?Sized> Write for &'a mut W {
153    fn set_style(&mut self, style: &Style) -> io::Result<()> {
154        <W as Write>::set_style(*self, style)
155    }
156}