longport/
serde_utils.rs

1#![allow(dead_code)]
2
3use std::str::FromStr;
4
5use serde::{Deserialize, Deserializer, Serializer, de::Error as _, ser::Error as _};
6use time::{Date, OffsetDateTime};
7
8pub(crate) mod date_opt {
9    use super::*;
10
11    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Date>, D::Error>
12    where
13        D: Deserializer<'de>,
14    {
15        let value = String::deserialize(deserializer)?;
16        if !value.is_empty() {
17            let datetime = Date::parse(
18                &value,
19                time::macros::format_description!("[year]-[month]-[day]"),
20            )
21            .map_err(D::Error::custom)?;
22            Ok(Some(datetime))
23        } else {
24            Ok(None)
25        }
26    }
27
28    pub(crate) fn serialize<S>(datetime: &Option<Date>, serializer: S) -> Result<S::Ok, S::Error>
29    where
30        S: Serializer,
31    {
32        match datetime {
33            Some(date) => serializer.serialize_str(
34                &date
35                    .format(time::macros::format_description!("[year]-[month]-[day]"))
36                    .unwrap(),
37            ),
38            None => serializer.serialize_none(),
39        }
40    }
41}
42
43pub(crate) mod timestamp {
44    use super::*;
45
46    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
47    where
48        D: Deserializer<'de>,
49    {
50        let value = String::deserialize(deserializer)?;
51        let value = value.parse::<i64>().map_err(D::Error::custom)?;
52        OffsetDateTime::from_unix_timestamp(value).map_err(D::Error::custom)
53    }
54
55    pub(crate) fn serialize<S>(datetime: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
56    where
57        S: Serializer,
58    {
59        serializer.collect_str(&datetime.unix_timestamp())
60    }
61}
62
63pub(crate) mod timestamp_opt {
64    use super::*;
65
66    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
67    where
68        D: Deserializer<'de>,
69    {
70        let Some(value) = <Option<String>>::deserialize(deserializer)? else {
71            return Ok(None);
72        };
73        if value.is_empty() {
74            return Ok(None);
75        }
76
77        let value = value.parse::<i64>().map_err(D::Error::custom)?;
78        if value != 0 {
79            let datetime = OffsetDateTime::from_unix_timestamp(value).map_err(D::Error::custom)?;
80            Ok(Some(datetime))
81        } else {
82            Ok(None)
83        }
84    }
85
86    pub(crate) fn serialize<S>(
87        datetime: &Option<OffsetDateTime>,
88        serializer: S,
89    ) -> Result<S::Ok, S::Error>
90    where
91        S: Serializer,
92    {
93        match datetime {
94            Some(datetime) => serializer.collect_str(&datetime.unix_timestamp()),
95            None => serializer.serialize_none(),
96        }
97    }
98}
99
100pub(crate) mod rfc3339_opt {
101    use super::*;
102
103    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<OffsetDateTime>, D::Error>
104    where
105        D: Deserializer<'de>,
106    {
107        let Some(value) = <Option<String>>::deserialize(deserializer)? else {
108            return Ok(None);
109        };
110        if value.is_empty() {
111            return Ok(None);
112        }
113        let datetime =
114            OffsetDateTime::parse(&value, &time::format_description::well_known::Rfc3339)
115                .map_err(D::Error::custom)?;
116        Ok(Some(datetime))
117    }
118
119    pub(crate) fn serialize<S>(
120        datetime: &Option<OffsetDateTime>,
121        serializer: S,
122    ) -> Result<S::Ok, S::Error>
123    where
124        S: Serializer,
125    {
126        match datetime {
127            Some(datetime) => serializer.collect_str(
128                &datetime
129                    .format(&time::format_description::well_known::Rfc3339)
130                    .map_err(S::Error::custom)?,
131            ),
132            None => serializer.serialize_none(),
133        }
134    }
135}
136
137pub(crate) mod risk_level {
138    use super::*;
139
140    pub(crate) fn serialize<S>(value: &i32, serializer: S) -> Result<S::Ok, S::Error>
141    where
142        S: Serializer,
143    {
144        serializer.collect_str(value)
145    }
146
147    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<i32, D::Error>
148    where
149        D: Deserializer<'de>,
150    {
151        let value = String::deserialize(deserializer)?;
152        if !value.is_empty() {
153            Ok(value
154                .parse::<i32>()
155                .map_err(|err| D::Error::custom(err.to_string()))?)
156        } else {
157            Ok(0)
158        }
159    }
160}
161
162pub(crate) mod decimal_empty_is_0 {
163    use rust_decimal::Decimal;
164
165    use super::*;
166
167    pub(crate) fn serialize<S>(value: &Decimal, serializer: S) -> Result<S::Ok, S::Error>
168    where
169        S: Serializer,
170    {
171        serializer.collect_str(&value)
172    }
173
174    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
175    where
176        D: Deserializer<'de>,
177    {
178        let value = String::deserialize(deserializer)?;
179        if !value.is_empty() {
180            let n = value.parse::<Decimal>().map_err(D::Error::custom)?;
181            Ok(n)
182        } else {
183            Ok(Decimal::ZERO)
184        }
185    }
186}
187
188pub(crate) mod decimal_opt_empty_is_none {
189    use rust_decimal::Decimal;
190
191    use super::*;
192
193    pub(crate) fn serialize<S>(value: &Option<Decimal>, serializer: S) -> Result<S::Ok, S::Error>
194    where
195        S: Serializer,
196    {
197        match value {
198            Some(value) => serializer.collect_str(&value),
199            _ => serializer.serialize_none(),
200        }
201    }
202
203    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
204    where
205        D: Deserializer<'de>,
206    {
207        let value = String::deserialize(deserializer)?;
208        if !value.is_empty() {
209            let n = value.parse::<Decimal>().map_err(D::Error::custom)?;
210            Ok(Some(n))
211        } else {
212            Ok(None)
213        }
214    }
215}
216
217pub(crate) mod decimal_opt_0_is_none {
218    use rust_decimal::Decimal;
219
220    use super::*;
221
222    pub(crate) fn serialize<S>(value: &Option<Decimal>, serializer: S) -> Result<S::Ok, S::Error>
223    where
224        S: Serializer,
225    {
226        match value {
227            Some(value) => serializer.collect_str(&value),
228            _ => serializer.serialize_none(),
229        }
230    }
231
232    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<Decimal>, D::Error>
233    where
234        D: Deserializer<'de>,
235    {
236        let value = String::deserialize(deserializer)?;
237        let n = value.parse::<Decimal>().map_err(D::Error::custom)?;
238        if !n.is_zero() { Ok(Some(n)) } else { Ok(None) }
239    }
240}
241
242pub(crate) mod trigger_status {
243    use super::*;
244    use crate::trade::TriggerStatus;
245
246    pub(crate) fn serialize<S>(
247        value: &Option<TriggerStatus>,
248        serializer: S,
249    ) -> Result<S::Ok, S::Error>
250    where
251        S: Serializer,
252    {
253        match value {
254            Some(value) => serializer.collect_str(value),
255            None => serializer.serialize_none(),
256        }
257    }
258
259    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<TriggerStatus>, D::Error>
260    where
261        D: Deserializer<'de>,
262    {
263        let value = String::deserialize(deserializer)?;
264        match value.as_str() {
265            "NOT_USED" => Ok(None),
266            _ => Ok(Some(
267                TriggerStatus::from_str(value.as_str()).unwrap_or_default(),
268            )),
269        }
270    }
271}
272
273pub(crate) mod outside_rth {
274    use super::*;
275    use crate::trade::OutsideRTH;
276
277    pub(crate) fn serialize<S>(value: &Option<OutsideRTH>, serializer: S) -> Result<S::Ok, S::Error>
278    where
279        S: Serializer,
280    {
281        match value {
282            Some(value) => serializer.collect_str(value),
283            None => serializer.serialize_none(),
284        }
285    }
286
287    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<OutsideRTH>, D::Error>
288    where
289        D: Deserializer<'de>,
290    {
291        let value = String::deserialize(deserializer)?;
292        match value.as_str() {
293            "UnknownOutsideRth" => Ok(None),
294            _ => Ok(Some(
295                OutsideRTH::from_str(value.as_str()).unwrap_or_default(),
296            )),
297        }
298    }
299}
300
301pub(crate) mod symbol_opt {
302    use super::*;
303
304    pub(crate) fn serialize<S>(value: &Option<String>, serializer: S) -> Result<S::Ok, S::Error>
305    where
306        S: Serializer,
307    {
308        match value {
309            Some(value) => serializer.serialize_str(value),
310            None => serializer.serialize_none(),
311        }
312    }
313
314    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
315    where
316        D: Deserializer<'de>,
317    {
318        match <Option<String>>::deserialize(deserializer)? {
319            Some(value) if value.is_empty() => Ok(None),
320            Some(value) => Ok(Some(value)),
321            _ => Ok(None),
322        }
323    }
324}
325
326pub(crate) mod int64_str {
327    use super::*;
328
329    pub(crate) fn serialize<S>(value: &i64, serializer: S) -> Result<S::Ok, S::Error>
330    where
331        S: Serializer,
332    {
333        serializer.collect_str(value)
334    }
335
336    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<i64, D::Error>
337    where
338        D: Deserializer<'de>,
339    {
340        let value = String::deserialize(deserializer)?;
341        Ok(value.parse::<i64>().unwrap_or_default())
342    }
343}
344
345pub(crate) mod int64_str_empty_is_none {
346    use super::*;
347
348    pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Option<i64>, D::Error>
349    where
350        D: Deserializer<'de>,
351    {
352        let value = String::deserialize(deserializer)?;
353        if !value.is_empty() {
354            Ok(Some(
355                value
356                    .parse::<i64>()
357                    .map_err(|err| D::Error::custom(err.to_string()))?,
358            ))
359        } else {
360            Ok(None)
361        }
362    }
363}