1use ntime::{Duration, Timestamp};
2use std::fmt;
3use std::thread;
4
5use crate::attributes::Map;
6use crate::level::Level;
7use crate::types::AttributeString;
8
9#[derive(Clone, Debug, PartialEq)]
12pub enum Scalar {
13 Bool(bool),
15 String(AttributeString),
17 Int(i64),
19 LongInt(i128),
21 Size(isize),
23 Uint(u64),
25 LongUint(u128),
27 Usize(usize),
29 Float(f64),
31}
32
33impl<'i> Scalar {
36 pub fn write_str<T: fmt::Write>(&self, out: &mut T, attrs: &Map) -> fmt::Result {
38 match &self {
39 Self::Bool(b) => write!(out, "{}", b),
40 Self::String(s) => write!(out, "\"{}\"", s.as_str(attrs)),
41 Self::Int(i) => write!(out, "{}", i),
42 Self::LongInt(i) => {
43 if *i < 1 {
44 write!(out, "-0x{:x}", -i)
45 } else {
46 write!(out, "0x{:x}", i)
47 }
48 }
49 Self::Size(s) => {
50 if *s < 1 {
51 write!(out, "-0x{:x}", -s)
52 } else {
53 write!(out, "0x{:x}", s)
54 }
55 }
56 Self::Uint(i) => write!(out, "{}", i),
57 Self::LongUint(u) => write!(out, "0x{:x}", u),
58 Self::Usize(u) => write!(out, "0x{:x}", u),
59 Self::Float(fl) => write!(out, "{}", fl),
60 }
61 }
62
63 pub fn to_array<const N: usize, T: ToScalarArray<'i, N>>(v: T) -> [Self; N] {
65 v.to_scalar_array()
66 }
67
68 pub fn into_string(&self, out: &mut String, attrs: &Map) {
70 out.clear();
71 self.write_str(out, attrs).expect("failed to serialize Scalar into_string()");
72 }
73}
74
75impl From<bool> for Scalar {
78 fn from(b: bool) -> Self {
79 Self::Bool(b)
80 }
81}
82
83impl From<String> for Scalar {
84 fn from(s: String) -> Self {
85 Self::String(AttributeString::from(s))
86 }
87}
88
89impl From<&'static str> for Scalar {
90 fn from(s: &'static str) -> Self {
91 Self::String(AttributeString::from(s))
92 }
93}
94
95impl From<Duration> for Scalar {
96 fn from(d: Duration) -> Self {
97 Self::Uint(d.as_secs())
98 }
99}
100
101impl From<&Duration> for Scalar {
102 fn from(d: &Duration) -> Self {
103 Self::Uint(d.as_secs())
104 }
105}
106
107impl From<Timestamp> for Scalar {
108 fn from(t: Timestamp) -> Self {
109 Self::Uint(t.as_secs())
110 }
111}
112
113impl From<&Timestamp> for Scalar {
114 fn from(t: &Timestamp) -> Self {
115 Self::Uint(t.as_secs())
116 }
117}
118
119impl From<thread::ThreadId> for Scalar {
120 fn from(t: thread::ThreadId) -> Self {
121 Self::String(AttributeString::from(format!("{:?}", t)))
122 }
123}
124
125impl From<&thread::ThreadId> for Scalar {
126 fn from(t: &thread::ThreadId) -> Self {
127 Self::String(AttributeString::from(format!("{:?}", t)))
128 }
129}
130
131impl From<Level> for Scalar {
132 fn from(t: Level) -> Self {
133 Self::String(AttributeString::from(t.to_string()))
134 }
135}
136
137impl From<&Level> for Scalar {
138 fn from(t: &Level) -> Self {
139 Self::String(AttributeString::from(t.to_string()))
140 }
141}
142
143macro_rules! cast_signed_to_scalar {
144 ($t: ty) => {
145 impl From<$t> for Scalar {
146 fn from(x: $t) -> Self {
147 Self::Int(x as i64)
148 }
149 }
150 };
151}
152
153cast_signed_to_scalar!(i8);
154cast_signed_to_scalar!(i16);
155cast_signed_to_scalar!(i32);
156cast_signed_to_scalar!(i64);
157
158impl From<i128> for Scalar {
159 fn from(x: i128) -> Self {
160 Self::LongInt(x)
161 }
162}
163
164impl From<isize> for Scalar {
165 fn from(x: isize) -> Self {
166 Self::Size(x)
167 }
168}
169
170macro_rules! cast_unsigned_to_scalar {
171 ($t: ty) => {
172 impl From<$t> for Scalar {
173 fn from(x: $t) -> Self {
174 Self::Uint(x as u64)
175 }
176 }
177 };
178}
179
180cast_unsigned_to_scalar!(u8);
181cast_unsigned_to_scalar!(u16);
182cast_unsigned_to_scalar!(u32);
183cast_unsigned_to_scalar!(u64);
184
185impl From<u128> for Scalar {
186 fn from(x: u128) -> Self {
187 Self::LongUint(x)
188 }
189}
190
191impl From<usize> for Scalar {
192 fn from(x: usize) -> Self {
193 Self::Usize(x)
194 }
195}
196
197macro_rules! cast_float_to_scalar {
198 ($t: ty) => {
199 impl From<$t> for Scalar {
200 fn from(x: $t) -> Self {
201 Self::Float(x as f64)
202 }
203 }
204 };
205}
206
207cast_float_to_scalar!(f32);
208cast_float_to_scalar!(f64);
209
210pub trait ToScalarArray<'t, const N: usize> {
214 fn to_scalar_array(self) -> [Scalar; N];
216}
217
218impl<'i, T: Into<Scalar>> ToScalarArray<'i, 1> for T
219where
220 Scalar: From<T>,
221{
222 fn to_scalar_array(self) -> [Scalar; 1] {
223 [Scalar::from(self)]
224 }
225}
226
227impl<'i, T: Into<Scalar>, const N: usize> ToScalarArray<'i, N> for [T; N]
228where
229 Scalar: From<T>,
230{
231 fn to_scalar_array(self) -> [Scalar; N] {
232 self.map(|x| Scalar::from(x))
233 }
234}
235
236#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn from_scalar() {
253 let short_string = "lalala";
254 let long_string = "this is a rather long string, which may be complicated";
255
256 assert_eq!(Scalar::from(true), Scalar::Bool(true));
257 assert_eq!(Scalar::from(short_string), Scalar::String(AttributeString::from(short_string)));
258 assert_eq!(Scalar::from(String::from(short_string)), Scalar::String(AttributeString::from(String::from(short_string))));
259 assert_eq!(Scalar::from(long_string), Scalar::String(long_string.into()));
260 assert_eq!(Scalar::from(String::from(long_string)), Scalar::String(AttributeString::from(String::from(long_string))));
261 assert_eq!(Scalar::from(-12 as i8), Scalar::Int(-12));
262 assert_eq!(Scalar::from(345 as i16), Scalar::Int(345));
263 assert_eq!(Scalar::from(-678 as i32), Scalar::Int(-678));
264 assert_eq!(Scalar::from(9012 as i64), Scalar::Int(9012));
265 assert_eq!(Scalar::from(-3456 as i128), Scalar::LongInt(-3456));
266 assert_eq!(Scalar::from(7890 as isize), Scalar::Size(7890));
267 assert_eq!(Scalar::from(12 as u8), Scalar::Uint(12));
268 assert_eq!(Scalar::from(345 as u16), Scalar::Uint(345));
269 assert_eq!(Scalar::from(678 as u32), Scalar::Uint(678));
270 assert_eq!(Scalar::from(9012 as u64), Scalar::Uint(9012));
271 assert_eq!(Scalar::from(3456 as u128), Scalar::LongUint(3456));
272 assert_eq!(Scalar::from(7890 as usize), Scalar::Usize(7890));
273 assert_eq!(Scalar::from(-123.456 as f32), Scalar::Float(-123.45600128173828));
275 assert_eq!(Scalar::from(789.012 as f64), Scalar::Float(789.012));
276 assert_eq!(Scalar::from(Duration::from_millis(12345)), Scalar::Uint(12));
277 assert_eq!(Scalar::from(&Duration::from_millis(67890)), Scalar::Uint(67));
278 assert_eq!(Scalar::from(Timestamp::from_millis(12345)), Scalar::Uint(12));
279 assert_eq!(Scalar::from(&Timestamp::from_millis(67890)), Scalar::Uint(67));
280 }
281
282 #[test]
283 fn into_string() {
284 for tc in [
285 (Scalar::Bool(true), "true"),
286 (Scalar::Bool(false), "false"),
287 (Scalar::String("".into()), "\"\""),
288 (Scalar::String("abcd 1234".into()), "\"abcd 1234\""),
289 (Scalar::String(String::from("heap String").into()), "\"heap String\""),
290 (Scalar::Int(-123), "-123"),
291 (Scalar::Int(456), "456"),
292 (Scalar::LongInt(-12345678901234567), "-0x2bdc545d6b4b87"),
293 (Scalar::LongInt(89801234567890123), "0x13f09bf3ecf84cb"),
294 (Scalar::Size(-12345678901234567), "-0x2bdc545d6b4b87"),
295 (Scalar::Size(89801234567890123), "0x13f09bf3ecf84cb"),
296 (Scalar::Uint(123456), "123456"),
297 (Scalar::LongUint(12345678901234567), "0x2bdc545d6b4b87"),
298 (Scalar::Usize(89801234567890123), "0x13f09bf3ecf84cb"),
299 (Scalar::Float(-1.2345), "-1.2345"),
300 (Scalar::Float(6.78901), "6.78901"),
301 ] {
302 let (s, want): (Scalar, &str) = tc;
303
304 let mut out = String::from("lalalala!");
305 let attrs = Map::new();
306
307 s.into_string(&mut out, &attrs);
308 assert_eq!(out, want);
309 }
310 }
311}