icinga2_api/
serde.rs

1//! Custom deserializers for various parts of the Icinga API results
2
3use serde::Deserialize;
4
5/// deserializes a unix timestamp with sub second accuracy
6/// (usually 6 digits after the decimal point for icinga)
7///
8/// # Errors
9///
10/// returns an error if the value can not be parsed as an f64
11/// or if it can not be converted from a unix timestamp to a
12/// [time::OffsetDateTime]
13pub fn deserialize_icinga_timestamp<'de, D>(
14    deserializer: D,
15) -> Result<time::OffsetDateTime, D::Error>
16where
17    D: serde::Deserializer<'de>,
18{
19    let f: f64 = f64::deserialize(deserializer)?;
20
21    let i = (f * 1_000_000_000f64) as i128;
22
23    time::OffsetDateTime::from_unix_timestamp_nanos(i).map_err(serde::de::Error::custom)
24}
25
26/// serialize a unix timestamp with sub second accuracy
27///
28/// # Errors
29///
30/// this should not return any errors
31pub fn serialize_icinga_timestamp<S>(
32    v: &time::OffsetDateTime,
33    serializer: S,
34) -> Result<S::Ok, S::Error>
35where
36    S: serde::Serializer,
37{
38    let ts = (v.unix_timestamp_nanos() as f64) / 1_000_000_000_f64;
39    <f64 as serde::Serialize>::serialize(&ts, serializer)
40}
41
42/// deserializes an optional unix timestamp with sub second accuracy
43/// (usually 6 digits after the decimal point for icinga)
44/// if the value is 0 return None
45///
46/// # Errors
47///
48/// returns an error if the value can not be parsed as an f64
49/// or if it can not be converted from a unix timestamp to a
50/// [time::OffsetDateTime]
51pub fn deserialize_optional_icinga_timestamp<'de, D>(
52    deserializer: D,
53) -> Result<Option<time::OffsetDateTime>, D::Error>
54where
55    D: serde::Deserializer<'de>,
56{
57    let f: f64 = f64::deserialize(deserializer)?;
58
59    if f == 0.0f64 {
60        Ok(None)
61    } else {
62        let i = (f * 1_000_000_000f64) as i128;
63
64        Ok(Some(
65            time::OffsetDateTime::from_unix_timestamp_nanos(i).map_err(serde::de::Error::custom)?,
66        ))
67    }
68}
69
70/// serialize a unix timestamp with sub second accuracy
71/// if the value is None serialize 0
72///
73/// # Errors
74///
75/// this should not return any errors
76pub fn serialize_optional_icinga_timestamp<S>(
77    v: &Option<time::OffsetDateTime>,
78    serializer: S,
79) -> Result<S::Ok, S::Error>
80where
81    S: serde::Serializer,
82{
83    let mut ts = 0f64;
84    if let Some(v) = v {
85        ts = (v.unix_timestamp_nanos() as f64) / 1_000_000_000_f64;
86    }
87    <f64 as serde::Serialize>::serialize(&ts, serializer)
88}
89
90/// deserialize an optional String where None is represented as
91/// an empty string
92///
93/// # Errors
94///
95/// returns an error if the value can not be interpreted as null or a String
96pub fn deserialize_empty_string_or_string<'de, D>(
97    deserializer: D,
98) -> Result<Option<String>, D::Error>
99where
100    D: serde::Deserializer<'de>,
101{
102    let s: Option<String> = Option::deserialize(deserializer)?;
103
104    if let Some(s) = s {
105        if s.is_empty() {
106            Ok(None)
107        } else {
108            Ok(Some(s))
109        }
110    } else {
111        Ok(None)
112    }
113}
114
115/// serialize an `Option<String>` as an empty string in the None case and normally
116/// otherwise
117///
118/// # Errors
119///
120/// this should not return any errors
121pub fn serialize_none_as_empty_string<S>(
122    v: &Option<String>,
123    serializer: S,
124) -> Result<S::Ok, S::Error>
125where
126    S: serde::Serializer,
127{
128    let mut s = &"".to_string();
129    if let Some(v) = v {
130        s = v;
131    }
132    <String as serde::Serialize>::serialize(s, serializer)
133}
134
135/// deserialize an optional value with a FromStr implementation where None is represented as
136/// an empty string
137///
138/// # Errors
139///
140/// returns an error if the value can not be interpreted as null or a String
141pub fn deserialize_empty_string_or_parse<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
142where
143    D: serde::Deserializer<'de>,
144    T: std::str::FromStr,
145    T::Err: std::fmt::Display,
146{
147    let s: Option<String> = Option::deserialize(deserializer)?;
148
149    if let Some(s) = s {
150        if s.is_empty() {
151            Ok(None)
152        } else {
153            Ok(Some(s.parse().map_err(serde::de::Error::custom)?))
154        }
155    } else {
156        Ok(None)
157    }
158}
159
160/// serialize an option value with a ToString implementation where None is represented as
161/// an empty string
162///
163/// # Errors
164///
165/// this should not return any errors
166pub fn serialize_none_as_empty_string_or_to_string<T, S>(
167    v: &Option<T>,
168    serializer: S,
169) -> Result<S::Ok, S::Error>
170where
171    S: serde::Serializer,
172    T: std::string::ToString,
173{
174    let mut s = "".to_string();
175    if let Some(v) = v {
176        s = v.to_string();
177    }
178    <String as serde::Serialize>::serialize(&s, serializer)
179}
180
181/// deserialize an integer as a time::Duration where the integer represents seconds
182///
183/// # Errors
184///
185/// returns an error if the value can not be parsed as an integer
186pub fn deserialize_seconds_as_duration<'de, D>(deserializer: D) -> Result<time::Duration, D::Error>
187where
188    D: serde::Deserializer<'de>,
189{
190    let i: i64 = i64::deserialize(deserializer)?;
191    Ok(time::Duration::seconds(i))
192}
193
194/// serialize a [time::Duration] as seconds
195///
196/// # Errors
197///
198/// this should not return any errors
199pub fn serialize_duration_as_seconds<S>(
200    v: &time::Duration,
201    serializer: S,
202) -> Result<S::Ok, S::Error>
203where
204    S: serde::Serializer,
205{
206    let d = v.whole_seconds();
207    <i64 as serde::Serialize>::serialize(&d, serializer)
208}
209
210/// deserialize an integer as a time::Duration where the integer represents seconds
211///
212/// # Errors
213///
214/// returns an error if the value can not be interpreted as null or an integer
215pub fn deserialize_optional_seconds_as_duration<'de, D>(
216    deserializer: D,
217) -> Result<Option<time::Duration>, D::Error>
218where
219    D: serde::Deserializer<'de>,
220{
221    let i: Option<i64> = Option::deserialize(deserializer)?;
222    if let Some(i) = i {
223        Ok(Some(time::Duration::seconds(i)))
224    } else {
225        Ok(None)
226    }
227}
228
229/// serialize an optional [time::Duration] as seconds
230///
231/// # Errors
232///
233/// this should not return any errors
234pub fn serialize_optional_duration_as_seconds<S>(
235    v: &Option<time::Duration>,
236    serializer: S,
237) -> Result<S::Ok, S::Error>
238where
239    S: serde::Serializer,
240{
241    let mut d: Option<i64> = None;
242    if let Some(v) = v {
243        d = Some(v.whole_seconds());
244    }
245    <Option<i64> as serde::Serialize>::serialize(&d, serializer)
246}