1use std::io::{Read, Write};
2
3use snops_checkpoint::{RetentionPolicy, RetentionRule, RetentionSpan};
4
5use super::{DataFormat, DataFormatReader, DataHeaderOf, DataReadError, DataWriteError};
6
7impl DataFormat for RetentionSpan {
8 type Header = u8;
9 const LATEST_HEADER: Self::Header = 1;
10
11 fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
12 match self {
13 RetentionSpan::Unlimited => 0u8.write_data(writer),
14 RetentionSpan::Minute(b) => {
15 1u8.write_data(writer)?;
16 b.write_data(writer)
17 }
18 RetentionSpan::Hour(b) => {
19 2u8.write_data(writer)?;
20 b.write_data(writer)
21 }
22 RetentionSpan::Day(b) => {
23 3u8.write_data(writer)?;
24 b.write_data(writer)
25 }
26 RetentionSpan::Week(b) => {
27 4u8.write_data(writer)?;
28 b.write_data(writer)
29 }
30 RetentionSpan::Month(b) => {
31 5u8.write_data(writer)?;
32 b.write_data(writer)
33 }
34 RetentionSpan::Year(b) => {
35 6u8.write_data(writer)?;
36 b.write_data(writer)
37 }
38 }
39 }
40
41 fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
42 if *header != Self::LATEST_HEADER {
43 return Err(DataReadError::unsupported(
44 "RetentionSpan",
45 Self::LATEST_HEADER,
46 *header,
47 ));
48 }
49 match reader.read_data(&())? {
50 0u8 => Ok(RetentionSpan::Unlimited),
51 1u8 => Ok(RetentionSpan::Minute(reader.read_data(&())?)),
52 2u8 => Ok(RetentionSpan::Hour(reader.read_data(&())?)),
53 3u8 => Ok(RetentionSpan::Day(reader.read_data(&())?)),
54 4u8 => Ok(RetentionSpan::Week(reader.read_data(&())?)),
55 5u8 => Ok(RetentionSpan::Month(reader.read_data(&())?)),
56 6u8 => Ok(RetentionSpan::Year(reader.read_data(&())?)),
57 n => Err(DataReadError::Custom(format!(
58 "invalid RetentionSpan discrminant: {n}",
59 ))),
60 }
61 }
62}
63
64impl DataFormat for RetentionPolicy {
65 type Header = (u8, DataHeaderOf<RetentionSpan>);
66
67 const LATEST_HEADER: Self::Header = (1, RetentionSpan::LATEST_HEADER);
68
69 fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
70 let rules = self
71 .rules
72 .iter()
73 .map(|r| (r.duration, r.keep))
74 .collect::<Vec<_>>();
75 rules.write_data(writer)
76 }
77
78 fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
79 if header.0 != Self::LATEST_HEADER.0 {
80 return Err(DataReadError::unsupported(
81 "RetentionPolicy",
82 Self::LATEST_HEADER.0,
83 header.0,
84 ));
85 }
86
87 let rules =
88 Vec::<(RetentionSpan, RetentionSpan)>::read_data(reader, &(header.1, header.1))?;
89 Ok(RetentionPolicy {
90 rules: rules
91 .into_iter()
92 .map(|(duration, keep)| RetentionRule { duration, keep })
93 .collect(),
94 })
95 }
96}
97
98#[cfg(test)]
99#[rustfmt::skip]
100mod test {
101 use crate::format::DataFormat;
102 use snops_checkpoint::{RetentionPolicy, RetentionSpan};
103
104
105 macro_rules! case {
106 ($name:ident, $ty:ty, $a:expr, $b:expr) => {
107 #[test]
108 fn $name() {
109 let mut data = Vec::new();
110 let value: $ty = $a.parse().unwrap();
111 value.write_data(&mut data).unwrap();
112 assert_eq!(data, $b);
113
114 let mut reader = &data[..];
115 let read_value = <$ty>::read_data(&mut reader, &<$ty as DataFormat>::LATEST_HEADER).unwrap();
116 assert_eq!(read_value, value);
117
118 }
119
120 };
121 }
122
123 case!(retention_span_unlimited, RetentionSpan, "U", [0]);
124 case!(retention_span_minute, RetentionSpan, "1m", [1, 1]);
125 case!(retention_span_hour, RetentionSpan, "1h", [2, 1]);
126 case!(retention_span_day, RetentionSpan, "1D", [3, 1]);
127 case!(retention_span_week, RetentionSpan, "1W", [4, 1]);
128 case!(retention_span_month, RetentionSpan, "1M", [5, 1]);
129 case!(retention_span_year, RetentionSpan, "1Y", [6, 1]);
130
131 case!(retention_policy, RetentionPolicy, "1m:1m,1h:1h,1D:1D,1W:1W,1M:1M,1Y:1Y", [
132 1, 6,
133 1, 1, 1, 1,
134 2, 1, 2, 1,
135 3, 1, 3, 1,
136 4, 1, 4, 1,
137 5, 1, 5, 1,
138 6, 1, 6, 1
139 ]);
140
141 case!(retention_policy_u_u, RetentionPolicy, "U:U", [
142 1, 1,
143 0, 0
144 ]);
145
146 case!(retention_policy_u_1y, RetentionPolicy, "U:1Y", [
147 1, 1,
148 0, 6, 1
149 ]);
150}