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}