1use crate::Error;
4use std::convert::{TryFrom, TryInto};
5
6pub use crate::tokenizers::time::repeat::Tokenizer;
9
10use crate::lines::common::TypedTime;
12
13#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
15pub struct Repeat {
16 pub interval: TypedTime,
17 pub duration: TypedTime,
18 pub offsets: Vec<TypedTime>,
19}
20
21impl<'a> TryFrom<Tokenizer<'a>> for Repeat {
22 type Error = Error;
23
24 fn try_from(tokenizer: Tokenizer<'a>) -> Result<Self, Self::Error> {
25 Ok(Self {
26 interval: tokenizer.interval.try_into().map_err(|e| {
27 Self::Error::parser_with_error("repeat interval", tokenizer.interval, e)
28 })?,
29 duration: tokenizer.duration.try_into().map_err(|e| {
30 Self::Error::parser_with_error("repeat duration", tokenizer.duration, e)
31 })?,
32 offsets: tokenizer
33 .offsets
34 .into_iter()
35 .map(TryInto::<TypedTime>::try_into)
36 .collect::<Result<Vec<_>, Error>>()?,
37 })
38 }
39}
40
41impl std::fmt::Display for Repeat {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(
44 f,
45 "r={} {} {}",
46 self.interval,
47 self.duration,
48 self.offsets
49 .iter()
50 .map(|i| i.to_string())
51 .collect::<Vec<_>>()
52 .join(" ")
53 )
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use chrono::Duration;
61
62 #[test]
63 fn from_tokenizer1() {
64 let tokenizer: Tokenizer = ("604800", "3600", vec!["0", "90000"]).into();
65
66 assert_eq!(
67 Repeat::try_from(tokenizer),
68 Ok(Repeat {
69 interval: TypedTime::None(Duration::seconds(604800)),
70 duration: TypedTime::None(Duration::seconds(3600)),
71 offsets: vec![
72 TypedTime::None(Duration::seconds(0)),
73 TypedTime::None(Duration::seconds(90000))
74 ]
75 })
76 );
77 }
78
79 #[test]
80 fn from_tokenizer2() {
81 let tokenizer: Tokenizer = ("7d", "1h", vec!["0", "25h"]).into();
82
83 assert_eq!(
84 Repeat::try_from(tokenizer),
85 Ok(Repeat {
86 interval: TypedTime::Days(Duration::seconds(604800)),
87 duration: TypedTime::Hours(Duration::seconds(3600)),
88 offsets: vec![
89 TypedTime::None(Duration::seconds(0)),
90 TypedTime::Hours(Duration::seconds(90000))
91 ]
92 })
93 );
94 }
95
96 #[test]
97 fn display1() {
98 let repeat = Repeat {
99 interval: TypedTime::Days(Duration::seconds(604800)),
100 duration: TypedTime::Hours(Duration::seconds(3600)),
101 offsets: vec![
102 TypedTime::None(Duration::seconds(0)),
103 TypedTime::Hours(Duration::seconds(90000)),
104 ],
105 };
106
107 assert_eq!(repeat.to_string(), "r=7d 1h 0 25h");
108 }
109
110 #[test]
111 fn display2() {
112 let repeat = Repeat {
113 interval: TypedTime::None(Duration::seconds(604800)),
114 duration: TypedTime::None(Duration::seconds(3600)),
115 offsets: vec![
116 TypedTime::None(Duration::seconds(0)),
117 TypedTime::None(Duration::seconds(90000)),
118 ],
119 };
120
121 assert_eq!(repeat.to_string(), "r=604800 3600 0 90000");
122 }
123}