chapters/
serialization.rs

1use crate::Image;
2use chrono::Duration;
3use serde::{Deserialize, Serialize};
4
5// Serialize impl
6impl Serialize for Image {
7    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
8    where
9        S: serde::Serializer,
10    {
11        match self {
12            Image::Url(url) => {
13                serializer.serialize_newtype_variant("image", 0, "Url", url.as_str())
14            }
15        }
16    }
17}
18
19pub fn float_to_duration_option<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
20where
21    D: serde::Deserializer<'de>,
22{
23    let f = match Option::<f64>::deserialize(deserializer) {
24        Ok(f) => f,
25        Err(_) => return Ok(None),
26    };
27    Ok(f.map(|f| Duration::milliseconds((f * 1000.0) as i64)))
28}
29
30pub fn float_to_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
31where
32    D: serde::Deserializer<'de>,
33{
34    let f = f64::deserialize(deserializer)?;
35    Ok(Duration::milliseconds((f * 1000.0) as i64))
36}
37
38pub fn duration_option_to_float_option<S>(
39    duration: &Option<Duration>,
40    serializer: S,
41) -> Result<S::Ok, S::Error>
42where
43    S: serde::Serializer,
44{
45    match duration {
46        Some(duration) => duration_to_float(duration, serializer),
47        None => serializer.serialize_none(),
48    }
49}
50
51pub fn duration_to_float<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
52where
53    S: serde::Serializer,
54{
55    // If float ends in .0 or doesn't even have a decimal point, serialize as an integer.
56    let float = duration.num_milliseconds() as f64 / 1000.0;
57    if float.fract() == 0.0 {
58        return serializer.serialize_i64(float as i64);
59    }
60    serializer.serialize_f64(float)
61}
62
63pub fn string_to_url<'de, D>(deserializer: D) -> Result<Option<url::Url>, D::Error>
64where
65    D: serde::Deserializer<'de>,
66{
67    let s = String::deserialize(deserializer)?;
68    Ok(url::Url::parse(&s).ok())
69}
70
71pub fn url_to_string<S>(url: &url::Url, serializer: S) -> Result<S::Ok, S::Error>
72where
73    S: serde::Serializer,
74{
75    serializer.serialize_str(url.as_str())
76}
77
78pub fn url_option_to_string<S>(url: &Option<url::Url>, serializer: S) -> Result<S::Ok, S::Error>
79where
80    S: serde::Serializer,
81{
82    match url {
83        Some(url) => url_to_string(url, serializer),
84        None => serializer.serialize_none(),
85    }
86}