eva_common/
tools.rs

1use crate::Error;
2use serde::{Deserialize, Deserializer, Serializer};
3use std::str::FromStr;
4use std::sync::atomic;
5use std::sync::Arc;
6use std::time::Duration;
7
8#[inline]
9pub fn get_eva_dir() -> String {
10    std::env::var("EVA_DIR").unwrap_or_else(|_| "/opt/eva4".to_owned())
11}
12
13#[inline]
14pub fn atomic_true() -> atomic::AtomicBool {
15    atomic::AtomicBool::new(true)
16}
17
18#[inline]
19pub fn arc_atomic_true() -> Arc<atomic::AtomicBool> {
20    Arc::new(atomic::AtomicBool::new(true))
21}
22
23#[derive(Debug)]
24pub enum SocketPath {
25    Tcp(String),
26    Udp(String),
27    Unix(String),
28}
29
30impl FromStr for SocketPath {
31    type Err = Error;
32
33    /// # Panics
34    ///
35    /// Will panic on internal errors
36    fn from_str(s: &str) -> Result<Self, Self::Err> {
37        Ok(if s.starts_with("tcp://") {
38            SocketPath::Tcp(s.strip_prefix("tcp://").unwrap().to_owned())
39        } else if s.starts_with("udp://") {
40            SocketPath::Udp(s.strip_prefix("udp://").unwrap().to_owned())
41        } else {
42            SocketPath::Unix(s.to_owned())
43        })
44    }
45}
46
47/// # Panics
48///
49/// Will panic of neither path nor default specified
50pub fn format_path(base: &str, path: Option<&str>, default: Option<&str>) -> String {
51    if let Some(p) = path {
52        if p.starts_with('/') {
53            p.to_owned()
54        } else {
55            format!("{}/{}", base, p)
56        }
57    } else if let Some(d) = default {
58        format!("{}/{}", base, d)
59    } else {
60        panic!("unable to format, neither path nor default specified");
61    }
62}
63
64#[macro_export]
65macro_rules! err_logger {
66    () => {
67        pub trait ErrLogger {
68            /// log error and forget the result
69            fn log_ef(self);
70            /// log error as debug and forget the result
71            fn log_efd(self);
72            /// log error and keep the result
73            fn log_err(self) -> Self;
74            /// log error as debug and keep the result
75            fn log_ed(self) -> Self;
76            /// log error and forget the result with message
77            fn log_ef_with(self, msg: impl ::std::fmt::Display);
78            /// log error as debug and forget the result with message
79            fn log_efd_with(self, msg: impl ::std::fmt::Display);
80            /// log error and keep the result with message
81            fn log_err_with(self, msg: impl ::std::fmt::Display) -> Self;
82            /// log error as debug and keep the result with message
83            fn log_ed_with(self, msg: impl ::std::fmt::Display) -> Self;
84        }
85
86        impl<R, E> ErrLogger for Result<R, E>
87        where
88            E: ::std::fmt::Display,
89        {
90            #[inline]
91            fn log_ef(self) {
92                if let Err(ref e) = self {
93                    ::log::error!("{}", e);
94                }
95            }
96            #[inline]
97            fn log_efd(self) {
98                if let Err(ref e) = self {
99                    ::log::debug!("{}", e);
100                }
101            }
102            #[inline]
103            fn log_err(self) -> Self {
104                if let Err(ref e) = self {
105                    ::log::error!("{}", e);
106                }
107                self
108            }
109            #[inline]
110            fn log_ed(self) -> Self {
111                if let Err(ref e) = self {
112                    ::log::debug!("{}", e);
113                }
114                self
115            }
116            #[inline]
117            fn log_ef_with(self, msg: impl ::std::fmt::Display) {
118                if let Err(ref e) = self {
119                    ::log::error!("{}: {}", msg, e);
120                }
121            }
122            #[inline]
123            fn log_efd_with(self, msg: impl ::std::fmt::Display) {
124                if let Err(ref e) = self {
125                    ::log::debug!("{}: {}", msg, e);
126                }
127            }
128            #[inline]
129            fn log_err_with(self, msg: impl ::std::fmt::Display) -> Self {
130                if let Err(ref e) = self {
131                    ::log::error!("{}: {}", msg, e);
132                }
133                self
134            }
135            #[inline]
136            fn log_ed_with(self, msg: impl ::std::fmt::Display) -> Self {
137                if let Err(ref e) = self {
138                    ::log::debug!("{}: {}", msg, e);
139                }
140                self
141            }
142        }
143    };
144}
145
146// atomic functions (not implemented in serde for certain archs)
147pub fn serialize_atomic_bool<S>(
148    value: &atomic::AtomicBool,
149    serializer: S,
150) -> Result<S::Ok, S::Error>
151where
152    S: Serializer,
153{
154    serializer.serialize_bool(value.load(atomic::Ordering::SeqCst))
155}
156
157pub fn deserialize_atomic_bool<'de, D>(deserializer: D) -> Result<atomic::AtomicBool, D::Error>
158where
159    D: Deserializer<'de>,
160{
161    let val = bool::deserialize(deserializer)?;
162    Ok(atomic::AtomicBool::new(val))
163}
164
165pub fn deserialize_arc_atomic_bool<'de, D>(
166    deserializer: D,
167) -> Result<Arc<atomic::AtomicBool>, D::Error>
168where
169    D: Deserializer<'de>,
170{
171    let val = bool::deserialize(deserializer)?;
172    Ok(Arc::new(atomic::AtomicBool::new(val)))
173}
174
175pub fn serialize_atomic_u64<S>(value: &atomic::AtomicU64, serializer: S) -> Result<S::Ok, S::Error>
176where
177    S: Serializer,
178{
179    serializer.serialize_u64(value.load(atomic::Ordering::SeqCst))
180}
181
182pub fn deserialize_atomic_u64<'de, D>(deserializer: D) -> Result<atomic::AtomicU64, D::Error>
183where
184    D: Deserializer<'de>,
185{
186    let val = u64::deserialize(deserializer)?;
187    Ok(atomic::AtomicU64::new(val))
188}
189
190pub fn deserialize_arc_atomic_u64<'de, D>(
191    deserializer: D,
192) -> Result<Arc<atomic::AtomicU64>, D::Error>
193where
194    D: Deserializer<'de>,
195{
196    let val = u64::deserialize(deserializer)?;
197    Ok(Arc::new(atomic::AtomicU64::new(val)))
198}
199
200pub fn serialize_duration_as_f64<S>(t: &Duration, s: S) -> Result<S::Ok, S::Error>
201where
202    S: Serializer,
203{
204    s.serialize_f64(t.as_secs_f64())
205}
206
207pub fn serialize_duration_as_u64<S>(t: &Duration, s: S) -> Result<S::Ok, S::Error>
208where
209    S: Serializer,
210{
211    s.serialize_u64(t.as_secs())
212}
213
214#[allow(clippy::cast_possible_truncation)]
215pub fn serialize_duration_as_micros<S>(t: &Duration, s: S) -> Result<S::Ok, S::Error>
216where
217    S: Serializer,
218{
219    s.serialize_u64(t.as_micros() as u64)
220}
221
222#[allow(clippy::cast_possible_truncation)]
223pub fn serialize_opt_duration_as_micros<S>(t: &Option<Duration>, s: S) -> Result<S::Ok, S::Error>
224where
225    S: Serializer,
226{
227    if let Some(ref dur) = t {
228        s.serialize_u64(dur.as_micros() as u64)
229    } else {
230        s.serialize_none()
231    }
232}
233
234#[allow(clippy::cast_possible_truncation)]
235pub fn serialize_duration_as_nanos<S>(t: &Duration, s: S) -> Result<S::Ok, S::Error>
236where
237    S: Serializer,
238{
239    s.serialize_u64(t.as_nanos() as u64)
240}
241
242#[allow(clippy::cast_possible_truncation)]
243pub fn serialize_opt_duration_as_nanos<S>(t: &Option<Duration>, s: S) -> Result<S::Ok, S::Error>
244where
245    S: Serializer,
246{
247    if let Some(ref dur) = t {
248        s.serialize_u64(dur.as_nanos() as u64)
249    } else {
250        s.serialize_none()
251    }
252}
253
254pub fn serialize_opt_duration_as_f64<S>(t: &Option<Duration>, s: S) -> Result<S::Ok, S::Error>
255where
256    S: Serializer,
257{
258    if let Some(ref dur) = t {
259        s.serialize_f64(dur.as_secs_f64())
260    } else {
261        s.serialize_none()
262    }
263}
264
265pub fn deserialize_duration_from_micros<'de, D>(deserializer: D) -> Result<Duration, D::Error>
266where
267    D: Deserializer<'de>,
268{
269    Ok(Duration::from_micros(u64::deserialize(deserializer)?))
270}
271
272pub fn deserialize_duration_from_nanos<'de, D>(deserializer: D) -> Result<Duration, D::Error>
273where
274    D: Deserializer<'de>,
275{
276    Ok(Duration::from_nanos(u64::deserialize(deserializer)?))
277}
278
279pub fn de_float_as_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
280where
281    D: Deserializer<'de>,
282{
283    Ok(Duration::from_secs_f64(f64::deserialize(deserializer)?))
284}
285
286pub fn de_opt_float_as_duration<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
287where
288    D: Deserializer<'de>,
289{
290    let t: Option<f64> = Option::deserialize(deserializer)?;
291    Ok(t.map(Duration::from_secs_f64))
292}
293
294#[allow(clippy::cast_possible_truncation)]
295#[allow(clippy::cast_sign_loss)]
296pub fn de_float_as_duration_us<'de, D>(deserializer: D) -> Result<Duration, D::Error>
297where
298    D: Deserializer<'de>,
299{
300    Ok(Duration::from_nanos(
301        (f64::deserialize(deserializer)? * 1000.0) as u64,
302    ))
303}
304
305#[allow(clippy::cast_possible_truncation)]
306#[allow(clippy::cast_sign_loss)]
307pub fn de_opt_float_as_duration_us<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
308where
309    D: Deserializer<'de>,
310{
311    let t: Option<f64> = Option::deserialize(deserializer)?;
312    Ok(t.map(|v| Duration::from_nanos((v * 1000.0) as u64)))
313}
314
315#[inline]
316pub fn default_true() -> bool {
317    true
318}
319
320#[inline]
321pub fn is_true(b: &bool) -> bool {
322    *b
323}