1use serde::de::{SeqAccess, Visitor};
6use serde::ser::SerializeSeq;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
16#[allow(clippy::struct_excessive_bools)]
17pub struct Perms {
18 pub read: bool,
20 pub write: bool,
22 pub events: bool,
24 pub additional_authorization: bool,
26 pub timed_write: bool,
28 pub hidden: bool,
30 pub write_response: bool,
32}
33
34impl Perms {
35 fn codes(self) -> Vec<&'static str> {
36 let mut v = Vec::new();
37 if self.read {
38 v.push("pr");
39 }
40 if self.write {
41 v.push("pw");
42 }
43 if self.events {
44 v.push("ev");
45 }
46 if self.additional_authorization {
47 v.push("aa");
48 }
49 if self.timed_write {
50 v.push("tw");
51 }
52 if self.hidden {
53 v.push("hd");
54 }
55 if self.write_response {
56 v.push("wr");
57 }
58 v
59 }
60}
61
62impl Serialize for Perms {
63 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
64 let codes = self.codes();
65 let mut seq = s.serialize_seq(Some(codes.len()))?;
66 for c in codes {
67 seq.serialize_element(c)?;
68 }
69 seq.end()
70 }
71}
72
73impl<'de> Deserialize<'de> for Perms {
74 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
75 struct PermsVisitor;
76 impl<'de> Visitor<'de> for PermsVisitor {
77 type Value = Perms;
78 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.write_str("an array of HAP permission codes")
80 }
81 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Perms, A::Error> {
82 let mut p = Perms::default();
83 while let Some(code) = seq.next_element::<String>()? {
84 match code.as_str() {
85 "pr" => p.read = true,
86 "pw" => p.write = true,
87 "ev" => p.events = true,
88 "aa" => p.additional_authorization = true,
89 "tw" => p.timed_write = true,
90 "hd" => p.hidden = true,
91 "wr" => p.write_response = true,
92 _ => {}
94 }
95 }
96 Ok(p)
97 }
98 }
99 d.deserialize_seq(PermsVisitor)
100 }
101}
102
103#[cfg(test)]
104#[allow(clippy::unwrap_used)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn parses_pr_pw_ev() {
111 let p: Perms = serde_json::from_str(r#"["pr","pw","ev"]"#).unwrap();
112 assert!(p.read && p.write && p.events);
113 assert!(!p.hidden);
114 }
115
116 #[test]
117 fn serializes_in_canonical_order() {
118 let p = Perms {
119 read: true,
120 events: true,
121 ..Perms::default()
122 };
123 assert_eq!(serde_json::to_string(&p).unwrap(), r#"["pr","ev"]"#);
124 }
125
126 #[test]
127 fn ignores_unknown_codes() {
128 let p: Perms = serde_json::from_str(r#"["pr","xx"]"#).unwrap();
129 assert!(p.read);
130 }
131}