kumo_dmarc/types/
report_failure.rs

1use instant_xml::ToXml;
2use serde::{Deserialize, Serialize};
3use std::fmt::Write;
4use std::str::FromStr;
5
6#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
7pub(crate) struct ReportFailure {
8    all_pass: bool,
9    any_pass: bool,
10    dkim: bool,
11    spf: bool,
12}
13
14impl ReportFailure {
15    pub fn new(all_pass: bool, any_pass: bool, dkim: bool, spf: bool) -> Self {
16        Self {
17            all_pass,
18            any_pass,
19            dkim,
20            spf,
21        }
22    }
23}
24
25impl ToXml for ReportFailure {
26    fn serialize<W: std::fmt::Write + ?Sized>(
27        &self,
28        _: Option<instant_xml::Id<'_>>,
29        serializer: &mut instant_xml::Serializer<W>,
30    ) -> Result<(), instant_xml::Error> {
31        serializer.write_str(self)
32    }
33}
34
35impl std::fmt::Display for ReportFailure {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        let values = [
38            (self.all_pass, '0'),
39            (self.any_pass, '1'),
40            (self.dkim, 'd'),
41            (self.spf, 's'),
42        ];
43
44        let mut first = true;
45        for (value, ch) in values.into_iter() {
46            if !value {
47                continue;
48            }
49
50            if !first {
51                f.write_char(':')?;
52            } else {
53                first = false;
54            }
55
56            f.write_char(ch)?;
57        }
58
59        Ok(())
60    }
61}
62
63impl FromStr for ReportFailure {
64    type Err = String;
65
66    fn from_str(value: &str) -> Result<Self, Self::Err> {
67        let mut new = Self::default();
68        for part in value.split(':') {
69            match part.trim() {
70                "0" => new.all_pass = true,
71                "1" => new.any_pass = true,
72                "d" => new.dkim = true,
73                "s" => new.spf = true,
74                _ => return Err(format!("invalid report failure {value:?}")),
75            }
76        }
77
78        Ok(new)
79    }
80}