sdp_rs/
time.rs

1use crate::{
2    lines::{Active, Repeat, Zone},
3    Error,
4};
5use std::convert::{TryFrom, TryInto};
6
7/// The time high level type tokenizer. It tokenizes all lines related to time (`a=`, `r=`, `z=`)
8/// at once.
9/// This is low level stuff and you shouldn't interact directly
10/// with it, unless you know what you are doing.
11pub use crate::tokenizers::time::Tokenizer;
12
13/// The time high level type. This type holds all types related to the time in SDP.
14#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
15pub struct Time {
16    pub active: Active,
17    pub repeat: Vec<Repeat>,
18    pub zone: Option<Zone>,
19}
20
21impl<'a> TryFrom<Tokenizer<'a>> for Time {
22    type Error = Error;
23
24    fn try_from(tokenizer: Tokenizer<'a>) -> Result<Self, Self::Error> {
25        Ok(Self {
26            active: tokenizer.active.try_into()?,
27            repeat: tokenizer
28                .repeat
29                .into_iter()
30                .map(TryInto::try_into)
31                .collect::<Result<Vec<_>, _>>()?,
32            zone: tokenizer.zone.map(TryInto::try_into).transpose()?,
33        })
34    }
35}
36
37impl std::fmt::Display for Time {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        write!(f, "{}", self.active)?;
40        for repeat in self.repeat.iter() {
41            write!(f, "\r\n{}", repeat)?
42        }
43        if let Some(zone) = &self.zone {
44            write!(f, "\r\n{}", zone)?
45        }
46
47        Ok(())
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::lines::{common::TypedTime, zone::ZonePart};
55    use chrono::Duration;
56
57    #[test]
58    fn from_tokenizer1() {
59        let tokenizer = Tokenizer {
60            active: ("3724394400", "3724398000").into(),
61            repeat: vec![
62                ("604800", "3600", vec!["0"]).into(),
63                ("7d", "1h", vec!["0", "25h"]).into(),
64            ],
65            zone: Some(vec![("3730928400", "-1h"), ("3749680800", "0")].into()),
66        };
67
68        assert_eq!(
69            Time::try_from(tokenizer),
70            Ok(Time {
71                active: Active {
72                    start: 3724394400,
73                    stop: 3724398000,
74                },
75                repeat: vec![
76                    Repeat {
77                        interval: TypedTime::None(Duration::seconds(604800)),
78                        duration: TypedTime::None(Duration::seconds(3600)),
79                        offsets: vec![TypedTime::None(Duration::seconds(0)),],
80                    },
81                    Repeat {
82                        interval: TypedTime::Days(Duration::seconds(604800)),
83                        duration: TypedTime::Hours(Duration::seconds(3600)),
84                        offsets: vec![
85                            TypedTime::None(Duration::seconds(0)),
86                            TypedTime::Hours(Duration::seconds(90000)),
87                        ],
88                    }
89                ],
90                zone: Some(Zone {
91                    parts: vec![
92                        ZonePart {
93                            adjustment_time: 3730928400,
94                            offset: TypedTime::Hours(Duration::hours(-1)),
95                        },
96                        ZonePart {
97                            adjustment_time: 3749680800,
98                            offset: TypedTime::None(Duration::hours(0)),
99                        },
100                    ],
101                })
102            })
103        );
104    }
105
106    #[test]
107    fn from_tokenizer2() {
108        let tokenizer = Tokenizer {
109            active: ("3724394400", "3724398000").into(),
110            repeat: vec![],
111            zone: None,
112        };
113
114        assert_eq!(
115            Time::try_from(tokenizer),
116            Ok(Time {
117                active: Active {
118                    start: 3724394400,
119                    stop: 3724398000,
120                },
121                repeat: vec![],
122                zone: None
123            })
124        );
125    }
126
127    #[test]
128    fn display1() {
129        let time = Time {
130            active: Active {
131                start: 3724394400,
132                stop: 3724398000,
133            },
134            repeat: vec![
135                Repeat {
136                    interval: TypedTime::None(Duration::seconds(604800)),
137                    duration: TypedTime::None(Duration::seconds(3600)),
138                    offsets: vec![TypedTime::None(Duration::seconds(0))],
139                },
140                Repeat {
141                    interval: TypedTime::Days(Duration::seconds(604800)),
142                    duration: TypedTime::Hours(Duration::seconds(3600)),
143                    offsets: vec![
144                        TypedTime::None(Duration::seconds(0)),
145                        TypedTime::Hours(Duration::seconds(90000)),
146                    ],
147                },
148            ],
149            zone: Some(Zone {
150                parts: vec![
151                    ZonePart {
152                        adjustment_time: 3730928400,
153                        offset: TypedTime::Hours(Duration::hours(-1)),
154                    },
155                    ZonePart {
156                        adjustment_time: 3749680800,
157                        offset: TypedTime::None(Duration::hours(0)),
158                    },
159                ],
160            }),
161        };
162
163        assert_eq!(
164            time.to_string(),
165            concat!(
166                "t=3724394400 3724398000\r\n",
167                "r=604800 3600 0\r\n",
168                "r=7d 1h 0 25h\r\n",
169                "z=3730928400 -1h 3749680800 0",
170            )
171        );
172    }
173
174    #[test]
175    fn display2() {
176        let time = Time {
177            active: Active {
178                start: 3724394400,
179                stop: 3724398000,
180            },
181            repeat: vec![],
182            zone: None,
183        };
184
185        assert_eq!(time.to_string(), concat!("t=3724394400 3724398000",));
186    }
187}