1use enumflags2::{bitflags, BitFlag, BitFlags};
7use serde::{
8 de::{self, Deserializer, Visitor},
9 ser::{self, Serializer},
10 Deserialize, Serialize,
11};
12use std::fmt;
13use zvariant::{Signature, Type};
14
15#[bitflags]
17#[repr(u32)]
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
19pub enum Interface {
20 #[serde(rename = "org.a11y.atspi.Accessible")]
22 Accessible,
23 #[serde(rename = "org.a11y.atspi.Action")]
25 Action,
26 #[serde(rename = "org.a11y.atspi.Application")]
28 Application,
29 #[serde(rename = "org.a11y.atspi.Cache")]
31 Cache,
32 #[serde(rename = "org.a11y.atspi.Collection")]
34 Collection,
35 #[serde(rename = "org.a11y.atspi.Component")]
37 Component,
38 #[serde(rename = "org.a11y.atspi.Document")]
40 Document,
41 #[serde(rename = "org.a11y.atspi.DeviceEventController")]
43 DeviceEventController,
44 #[serde(rename = "org.a11y.atspi.DeviceEventListener")]
46 DeviceEventListener,
47 #[serde(rename = "org.a11y.atspi.EditableText")]
49 EditableText,
50 #[serde(rename = "org.a11y.atspi.Hyperlink")]
52 Hyperlink,
53 #[serde(rename = "org.a11y.atspi.Hypertext")]
55 Hypertext,
56 #[serde(rename = "org.a11y.atspi.Image")]
58 Image,
59 #[serde(rename = "org.a11y.atspi.Registry")]
61 Registry,
62 #[serde(rename = "org.a11y.atspi.Selection")]
64 Selection,
65 #[serde(rename = "org.a11y.atspi.Socket")]
67 Socket,
68 #[serde(rename = "org.a11y.atspi.Table")]
70 Table,
71 #[serde(rename = "org.a11y.atspi.TableCell")]
73 TableCell,
74 #[serde(rename = "org.a11y.atspi.Text")]
76 Text,
77 #[serde(rename = "org.a11y.atspi.Value")]
79 Value,
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
84pub struct InterfaceSet(BitFlags<Interface>);
85
86impl InterfaceSet {
87 pub fn new<B: Into<BitFlags<Interface>>>(value: B) -> Self {
88 Self(value.into())
89 }
90
91 #[must_use]
92 pub fn empty() -> InterfaceSet {
93 InterfaceSet(Interface::empty())
94 }
95
96 #[must_use]
97 pub fn bits(&self) -> u32 {
98 self.0.bits()
99 }
100
101 #[must_use]
102 pub fn all() -> InterfaceSet {
103 InterfaceSet(Interface::all())
104 }
105
106 pub fn contains<B: Into<BitFlags<Interface>>>(self, other: B) -> bool {
107 self.0.contains(other)
108 }
109
110 pub fn insert<B: Into<BitFlags<Interface>>>(&mut self, other: B) {
111 self.0.insert(other);
112 }
113
114 pub fn iter(self) -> impl Iterator<Item = Interface> {
115 self.0.iter()
116 }
117}
118
119impl<'de> de::Deserialize<'de> for InterfaceSet {
120 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
121 where
122 D: Deserializer<'de>,
123 {
124 struct InterfaceSetVisitor;
125
126 impl<'de> Visitor<'de> for InterfaceSetVisitor {
127 type Value = InterfaceSet;
128
129 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
130 formatter.write_str("a sequence comprised of valid AT-SPI interface names")
131 }
132
133 fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
134 where
135 D: Deserializer<'de>,
136 {
137 match <Vec<Interface> as Deserialize>::deserialize(deserializer) {
138 Ok(interfaces) => Ok(InterfaceSet(BitFlags::from_iter(interfaces))),
139 Err(e) => Err(e),
140 }
141 }
142 }
143
144 deserializer.deserialize_newtype_struct("InterfaceSet", InterfaceSetVisitor)
145 }
146}
147
148impl ser::Serialize for InterfaceSet {
149 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: Serializer,
152 {
153 serializer
154 .serialize_newtype_struct("InterfaceSet", &self.0.iter().collect::<Vec<Interface>>())
155 }
156}
157
158impl Type for InterfaceSet {
159 fn signature() -> Signature<'static> {
160 <Vec<String> as Type>::signature()
161 }
162}
163
164impl From<Interface> for InterfaceSet {
165 fn from(value: Interface) -> Self {
166 Self(value.into())
167 }
168}
169
170impl std::ops::BitAnd for InterfaceSet {
171 type Output = InterfaceSet;
172
173 fn bitand(self, other: Self) -> Self::Output {
174 InterfaceSet(self.0 & other.0)
175 }
176}
177
178impl std::ops::BitXor for InterfaceSet {
179 type Output = InterfaceSet;
180
181 fn bitxor(self, other: Self) -> Self::Output {
182 InterfaceSet(self.0 ^ other.0)
183 }
184}
185
186impl std::ops::BitOr for InterfaceSet {
187 type Output = InterfaceSet;
188
189 fn bitor(self, other: Self) -> Self::Output {
190 InterfaceSet(self.0 | other.0)
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::{Interface, InterfaceSet};
197 use zvariant::serialized::Data;
198 use zvariant::{serialized::Context, to_bytes, LE};
199
200 #[test]
201 fn serialize_empty_interface_set() {
202 let ctxt = Context::new_dbus(LE, 0);
203 let encoded = to_bytes(ctxt, &InterfaceSet::empty()).unwrap();
204 assert_eq!(encoded.bytes(), &[0, 0, 0, 0]);
205 }
206
207 #[test]
208 fn deserialize_empty_interface_set() {
209 let ctxt = Context::new_dbus(LE, 0);
210 let encoded = to_bytes(ctxt, &InterfaceSet::empty()).unwrap();
211 let (decoded, _) = encoded.deserialize::<InterfaceSet>().unwrap();
212 assert_eq!(decoded, InterfaceSet::empty());
213 }
214
215 #[test]
216 fn serialize_interface_set_accessible() {
217 let ctxt = Context::new_dbus(LE, 0);
218 let encoded = to_bytes(ctxt, &InterfaceSet::new(Interface::Accessible)).unwrap();
219 assert_eq!(
220 encoded.bytes(),
221 &[
222 30, 0, 0, 0, 25, 0, 0, 0, 111, 114, 103, 46, 97, 49, 49, 121, 46, 97, 116, 115,
223 112, 105, 46, 65, 99, 99, 101, 115, 115, 105, 98, 108, 101, 0
224 ]
225 );
226 }
227
228 #[test]
229 fn deserialize_interface_set_accessible() {
230 let ctxt = Context::new_dbus(LE, 0);
231 let data = Data::new::<&[u8]>(
232 &[
233 30, 0, 0, 0, 25, 0, 0, 0, 111, 114, 103, 46, 97, 49, 49, 121, 46, 97, 116, 115,
234 112, 105, 46, 65, 99, 99, 101, 115, 115, 105, 98, 108, 101, 0,
235 ],
236 ctxt,
237 );
238
239 let (ifaceset, _) = data.deserialize::<InterfaceSet>().unwrap();
240 assert_eq!(ifaceset, InterfaceSet::new(Interface::Accessible));
241 }
242
243 #[test]
244 fn can_handle_multiple_interfaces() {
245 let ctxt = Context::new_dbus(LE, 0);
246 let object =
247 InterfaceSet::new(Interface::Accessible | Interface::Action | Interface::Component);
248 let encoded = to_bytes(ctxt, &object).unwrap();
249 let (decoded, _) = encoded.deserialize::<InterfaceSet>().unwrap();
250 assert!(object == decoded);
251 }
252}