tracing_formatters/
log_value.rs

1use crate::severity::Severity;
2use crate::util::{IntegerConversionError, UtilTryInto};
3use chrono::{DateTime, NaiveDateTime, ParseError, Utc};
4use core::fmt::{Debug, Display, Formatter};
5use core::str::FromStr;
6
7pub enum LogValueConvertionError {
8    FailedToConvertToDateTimeUtc(String),
9    FailedToConvertToU32(String),
10    FailedToConvertToI32(String),
11    UnableToCreateTimestampFrom(i64),
12    IntegerConversionError(IntegerConversionError),
13}
14
15impl From<IntegerConversionError> for LogValueConvertionError {
16    fn from(e: IntegerConversionError) -> Self {
17        Self::IntegerConversionError(e)
18    }
19}
20
21#[derive(Debug, Clone, PartialEq)]
22pub enum LogValue {
23    I64(i64),
24    U64(u64),
25    F64(f64),
26    Bool(bool),
27    String(String),
28    TimeStamp(DateTime<Utc>),
29    Severity(Severity),
30    Debug(String),
31}
32
33impl From<i64> for LogValue {
34    fn from(v: i64) -> Self {
35        LogValue::I64(v)
36    }
37}
38
39impl From<u64> for LogValue {
40    fn from(v: u64) -> Self {
41        LogValue::U64(v)
42    }
43}
44
45impl From<f64> for LogValue {
46    fn from(v: f64) -> Self {
47        LogValue::F64(v)
48    }
49}
50
51impl From<bool> for LogValue {
52    fn from(v: bool) -> Self {
53        LogValue::Bool(v)
54    }
55}
56
57impl From<String> for LogValue {
58    fn from(v: String) -> Self {
59        LogValue::String(v)
60    }
61}
62
63impl From<&str> for LogValue {
64    fn from(v: &str) -> Self {
65        LogValue::String(v.to_owned())
66    }
67}
68
69impl Display for LogValue {
70    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
71        match self {
72            LogValue::I64(t) => write!(f, "{}", t),
73            LogValue::U64(t) => write!(f, "{}", t),
74            LogValue::F64(t) => write!(f, "{}", t),
75            LogValue::Bool(t) => write!(f, "{}", t),
76            LogValue::String(t) => write!(f, "{}", t),
77            LogValue::Debug(t) => write!(f, "{}", t),
78            LogValue::TimeStamp(t) => write!(f, "{}", t),
79            LogValue::Severity(t) => write!(f, "{}", t),
80        }
81    }
82}
83
84impl TryFrom<LogValue> for DateTime<Utc> {
85    type Error = LogValueConvertionError;
86
87    fn try_from(value: LogValue) -> Result<Self, Self::Error> {
88        match value {
89            LogValue::I64(i) => NaiveDateTime::from_timestamp_opt(i, 0)
90                .ok_or(LogValueConvertionError::UnableToCreateTimestampFrom(i))
91                .map(|t| DateTime::from_utc(t, Utc)),
92            LogValue::U64(u) => NaiveDateTime::from_timestamp_opt(u as i64, 0)
93                .ok_or(LogValueConvertionError::UnableToCreateTimestampFrom(
94                    u as i64,
95                ))
96                .map(|t| DateTime::from_utc(t, Utc)),
97            LogValue::F64(f) => f
98                .util_try_into()
99                .map_err(LogValueConvertionError::from)
100                .and_then(|t| {
101                    NaiveDateTime::from_timestamp_opt(t, 0)
102                        .ok_or(LogValueConvertionError::UnableToCreateTimestampFrom(t))
103                })
104                .map(|t| DateTime::from_utc(t, Utc)),
105            LogValue::Bool(_) => Err(LogValueConvertionError::FailedToConvertToDateTimeUtc(
106                "LogValue is a boolean, unable to convert".to_string(),
107            )),
108            LogValue::String(s) => DateTime::from_str(s.as_str()).map_err(|e: ParseError| {
109                LogValueConvertionError::FailedToConvertToDateTimeUtc(e.to_string())
110            }),
111            LogValue::Debug(s) => DateTime::from_str(s.as_str()).map_err(|e: ParseError| {
112                LogValueConvertionError::FailedToConvertToDateTimeUtc(e.to_string())
113            }),
114            LogValue::TimeStamp(t) => Ok(t),
115            LogValue::Severity(t) => Err(LogValueConvertionError::FailedToConvertToDateTimeUtc(
116                "LogValue is a Severity and cannot be convert".to_string(),
117            )),
118        }
119    }
120}
121
122impl From<LogValue> for String {
123    fn from(value: LogValue) -> Self {
124        value.to_string()
125    }
126}
127
128impl TryFrom<LogValue> for u32 {
129    type Error = LogValueConvertionError;
130
131    fn try_from(value: LogValue) -> Result<Self, Self::Error> {
132        match value {
133            LogValue::I64(i) => i.util_try_into().map_err(LogValueConvertionError::from),
134            LogValue::U64(u) => u.util_try_into().map_err(LogValueConvertionError::from),
135            LogValue::F64(f) => f.util_try_into().map_err(LogValueConvertionError::from),
136            LogValue::Bool(_) => Err(LogValueConvertionError::FailedToConvertToU32(
137                "LogValue is a Bool, unable to convert".to_string(),
138            )),
139            LogValue::String(s) => Err(LogValueConvertionError::FailedToConvertToU32(
140                "LogValue is a String, unable to convert".to_string(),
141            )),
142            LogValue::Debug(s) => Err(LogValueConvertionError::FailedToConvertToU32(
143                "LogValue is a String, unable to convert".to_string(),
144            )),
145            LogValue::TimeStamp(t) => Ok(t.timestamp() as u32),
146            LogValue::Severity(t) => Err(LogValueConvertionError::FailedToConvertToU32(
147                "LogValue is a Severity and cannot be convert".to_string(),
148            )),
149        }
150    }
151}
152
153impl TryFrom<LogValue> for i32 {
154    type Error = LogValueConvertionError;
155
156    fn try_from(value: LogValue) -> Result<Self, Self::Error> {
157        match value {
158            LogValue::I64(i) => i.util_try_into().map_err(LogValueConvertionError::from),
159            LogValue::U64(u) => u.util_try_into().map_err(LogValueConvertionError::from),
160            LogValue::F64(f) => f.util_try_into().map_err(LogValueConvertionError::from),
161            LogValue::Bool(_) => Err(LogValueConvertionError::FailedToConvertToI32(
162                "LogValue is a Bool, unable to convert".to_string(),
163            )),
164            LogValue::String(s) => Err(LogValueConvertionError::FailedToConvertToI32(
165                "LogValue is a String, unable to convert".to_string(),
166            )),
167            LogValue::Debug(s) => Err(LogValueConvertionError::FailedToConvertToI32(
168                "LogValue is a String, unable to convert".to_string(),
169            )),
170            LogValue::TimeStamp(t) => Ok(t.timestamp() as i32),
171            LogValue::Severity(t) => Err(LogValueConvertionError::FailedToConvertToI32(
172                "LogValue is a Severity and cannot be convert".to_string(),
173            )),
174        }
175    }
176}
177
178impl From<LogValue> for Vec<String> {
179    fn from(value: LogValue) -> Self {
180        vec![value.to_string()]
181    }
182}
183
184impl From<u32> for LogValue {
185    fn from(u: u32) -> Self {
186        LogValue::U64(u as u64)
187    }
188}
189impl From<Option<u32>> for LogValue {
190    fn from(opt: Option<u32>) -> Self {
191        match opt {
192            None => LogValue::Debug("".to_string()),
193            Some(u) => LogValue::U64(u as u64),
194        }
195    }
196}
197impl From<Option<&str>> for LogValue {
198    fn from(opt: Option<&str>) -> Self {
199        match opt {
200            None => LogValue::Debug("".to_string()),
201            Some(s) => LogValue::String(s.to_string()),
202        }
203    }
204}
205
206#[cfg(feature = "bunyan")]
207impl From<&LogValue> for serde_json::Value {
208    fn from(v: &LogValue) -> Self {
209        match v {
210            LogValue::I64(t) => t.clone().into(),
211            LogValue::U64(t) => t.clone().into(),
212            LogValue::F64(t) => t.clone().into(),
213            LogValue::Bool(t) => t.clone().into(),
214            LogValue::String(t) => t.clone().into(),
215            LogValue::TimeStamp(t) => t.to_string().into(),
216            LogValue::Severity(t) => t.to_string().into(),
217            LogValue::Debug(t) => t.clone().into(),
218        }
219    }
220}