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