atspi_common/
interface.rs

1//! Conversion functions and types representing a set of [`Interface`]s.
2//!
3//! Each `AccessibleProxy` will implement some set of these interfaces,
4//! represented by a [`InterfaceSet`].
5
6use 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/// AT-SPI interfaces an accessible object can implement.
16#[bitflags]
17#[repr(u32)]
18#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
19pub enum Interface {
20	/// Interface to indicate implementation of `AccessibleProxy`.
21	#[serde(rename = "org.a11y.atspi.Accessible")]
22	Accessible,
23	/// Interface to indicate implementation of `ActionProxy`.
24	#[serde(rename = "org.a11y.atspi.Action")]
25	Action,
26	/// Interface to indicate implementation of `ApplicationProxy`.
27	#[serde(rename = "org.a11y.atspi.Application")]
28	Application,
29	/// Interface to indicate implementation of `CacheProxy`.
30	#[serde(rename = "org.a11y.atspi.Cache")]
31	Cache,
32	/// Interface to indicate implementation of `CollectionProxy`.
33	#[serde(rename = "org.a11y.atspi.Collection")]
34	Collection,
35	/// Interface to indicate implementation of `ComponentProxy`.
36	#[serde(rename = "org.a11y.atspi.Component")]
37	Component,
38	/// Interface to indicate implementation of `DocumentProxy`.
39	#[serde(rename = "org.a11y.atspi.Document")]
40	Document,
41	/// Interface to indicate implementation of `DeviceEventControllerProxy`.
42	#[serde(rename = "org.a11y.atspi.DeviceEventController")]
43	DeviceEventController,
44	/// Interface to indicate implementation of `DeviceEventListenerProxy`.
45	#[serde(rename = "org.a11y.atspi.DeviceEventListener")]
46	DeviceEventListener,
47	/// Interface to indicate implementation of `EditableTextProxy`.
48	#[serde(rename = "org.a11y.atspi.EditableText")]
49	EditableText,
50	/// Interface to indicate implementation of `HyperlinkProxy`.
51	#[serde(rename = "org.a11y.atspi.Hyperlink")]
52	Hyperlink,
53	/// Interface to indicate implementation of `HypertextProxy`.
54	#[serde(rename = "org.a11y.atspi.Hypertext")]
55	Hypertext,
56	/// Interface to indicate implementation of `ImageProxy`.
57	#[serde(rename = "org.a11y.atspi.Image")]
58	Image,
59	/// Interface to indicate implementation of `RegistryProxy`.
60	#[serde(rename = "org.a11y.atspi.Registry")]
61	Registry,
62	/// Interface to indicate implementation of `SelectionProxy`.
63	#[serde(rename = "org.a11y.atspi.Selection")]
64	Selection,
65	/// Interface to indicate implementation of `SocketProxy`.
66	#[serde(rename = "org.a11y.atspi.Socket")]
67	Socket,
68	/// Interface to indicate implementation of `TableProxy`.
69	#[serde(rename = "org.a11y.atspi.Table")]
70	Table,
71	/// Interface to indicate implementation of `TableCellProxy`.
72	#[serde(rename = "org.a11y.atspi.TableCell")]
73	TableCell,
74	/// Interface to indicate implementation of `TextProxy`.
75	#[serde(rename = "org.a11y.atspi.Text")]
76	Text,
77	/// Interface to indicate implementation of `ValueProxy`.
78	#[serde(rename = "org.a11y.atspi.Value")]
79	Value,
80}
81
82/// A collection type which encodes the AT-SPI interfaces an accessible object has implemented.
83#[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	#[must_use]
115	pub fn iter(&self) -> enumflags2::Iter<Interface> {
116		self.0.iter()
117	}
118}
119
120impl IntoIterator for InterfaceSet {
121	type IntoIter = enumflags2::Iter<Interface>;
122	type Item = Interface;
123
124	fn into_iter(self) -> Self::IntoIter {
125		self.iter()
126	}
127}
128
129impl IntoIterator for &InterfaceSet {
130	type IntoIter = enumflags2::Iter<Interface>;
131	type Item = Interface;
132
133	fn into_iter(self) -> Self::IntoIter {
134		self.iter()
135	}
136}
137
138impl Default for InterfaceSet {
139	fn default() -> Self {
140		Self::empty()
141	}
142}
143
144impl<'de> de::Deserialize<'de> for InterfaceSet {
145	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146	where
147		D: Deserializer<'de>,
148	{
149		struct InterfaceSetVisitor;
150
151		impl<'de> Visitor<'de> for InterfaceSetVisitor {
152			type Value = InterfaceSet;
153
154			fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
155				formatter.write_str("a sequence comprised of valid AT-SPI interface names")
156			}
157
158			fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
159			where
160				D: Deserializer<'de>,
161			{
162				match <Vec<Interface> as Deserialize>::deserialize(deserializer) {
163					Ok(interfaces) => Ok(InterfaceSet(BitFlags::from_iter(interfaces))),
164					Err(e) => Err(e),
165				}
166			}
167		}
168
169		deserializer.deserialize_newtype_struct("InterfaceSet", InterfaceSetVisitor)
170	}
171}
172
173impl ser::Serialize for InterfaceSet {
174	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
175	where
176		S: Serializer,
177	{
178		serializer
179			.serialize_newtype_struct("InterfaceSet", &self.0.iter().collect::<Vec<Interface>>())
180	}
181}
182
183impl Type for InterfaceSet {
184	const SIGNATURE: &'static Signature = <Vec<String> as Type>::SIGNATURE;
185}
186
187impl FromIterator<Interface> for InterfaceSet {
188	fn from_iter<T: IntoIterator<Item = Interface>>(iter: T) -> Self {
189		Self(BitFlags::from_iter(iter))
190	}
191}
192
193impl<'a> FromIterator<&'a Interface> for InterfaceSet {
194	fn from_iter<I: IntoIterator<Item = &'a Interface>>(iter: I) -> Self {
195		InterfaceSet(iter.into_iter().copied().collect())
196	}
197}
198
199impl From<Interface> for InterfaceSet {
200	fn from(value: Interface) -> Self {
201		Self(value.into())
202	}
203}
204
205impl std::ops::BitAnd for InterfaceSet {
206	type Output = InterfaceSet;
207
208	fn bitand(self, other: Self) -> Self::Output {
209		InterfaceSet(self.0 & other.0)
210	}
211}
212
213impl std::ops::BitXor for InterfaceSet {
214	type Output = InterfaceSet;
215
216	fn bitxor(self, other: Self) -> Self::Output {
217		InterfaceSet(self.0 ^ other.0)
218	}
219}
220
221impl std::ops::BitOr for InterfaceSet {
222	type Output = InterfaceSet;
223
224	fn bitor(self, other: Self) -> Self::Output {
225		InterfaceSet(self.0 | other.0)
226	}
227}
228
229#[cfg(test)]
230mod tests {
231	use super::{Interface, InterfaceSet};
232	use zvariant::serialized::Data;
233	use zvariant::{serialized::Context, to_bytes, LE};
234
235	#[test]
236	fn serialize_empty_interface_set() {
237		let ctxt = Context::new_dbus(LE, 0);
238		let encoded = to_bytes(ctxt, &InterfaceSet::empty()).unwrap();
239		assert_eq!(encoded.bytes(), &[0, 0, 0, 0]);
240	}
241
242	#[test]
243	fn deserialize_empty_interface_set() {
244		let ctxt = Context::new_dbus(LE, 0);
245		let encoded = to_bytes(ctxt, &InterfaceSet::empty()).unwrap();
246		let (decoded, _) = encoded.deserialize::<InterfaceSet>().unwrap();
247		assert_eq!(decoded, InterfaceSet::empty());
248	}
249
250	#[test]
251	fn serialize_interface_set_accessible() {
252		let ctxt = Context::new_dbus(LE, 0);
253		let encoded = to_bytes(ctxt, &InterfaceSet::new(Interface::Accessible)).unwrap();
254		assert_eq!(
255			encoded.bytes(),
256			&[
257				30, 0, 0, 0, 25, 0, 0, 0, 111, 114, 103, 46, 97, 49, 49, 121, 46, 97, 116, 115,
258				112, 105, 46, 65, 99, 99, 101, 115, 115, 105, 98, 108, 101, 0
259			]
260		);
261	}
262
263	#[test]
264	fn deserialize_interface_set_accessible() {
265		let ctxt = Context::new_dbus(LE, 0);
266		let data = Data::new::<&[u8]>(
267			&[
268				30, 0, 0, 0, 25, 0, 0, 0, 111, 114, 103, 46, 97, 49, 49, 121, 46, 97, 116, 115,
269				112, 105, 46, 65, 99, 99, 101, 115, 115, 105, 98, 108, 101, 0,
270			],
271			ctxt,
272		);
273
274		let (ifaceset, _) = data.deserialize::<InterfaceSet>().unwrap();
275		assert_eq!(ifaceset, InterfaceSet::new(Interface::Accessible));
276	}
277
278	#[test]
279	fn can_handle_multiple_interfaces() {
280		let ctxt = Context::new_dbus(LE, 0);
281		let object =
282			InterfaceSet::new(Interface::Accessible | Interface::Action | Interface::Component);
283		let encoded = to_bytes(ctxt, &object).unwrap();
284		let (decoded, _) = encoded.deserialize::<InterfaceSet>().unwrap();
285		assert!(object == decoded);
286	}
287
288	// The order of appearance of the interfaces is equal to the order in the enum.
289	#[test]
290	fn iterator_on_interface_set() {
291		let set =
292			InterfaceSet::new(Interface::Accessible | Interface::Action | Interface::Component);
293		let mut iter = set.into_iter();
294		assert_eq!(iter.next(), Some(Interface::Accessible));
295		assert_eq!(iter.next(), Some(Interface::Action));
296		assert_eq!(iter.next(), Some(Interface::Component));
297		assert_eq!(iter.next(), None);
298	}
299
300	#[test]
301	fn iterator_on_interface_set_ref() {
302		let set = InterfaceSet::new(Interface::Text | Interface::Collection | Interface::Component);
303		let mut iter = (&set).into_iter();
304		assert_eq!(iter.next(), Some(Interface::Collection));
305		assert_eq!(iter.next(), Some(Interface::Component));
306		assert_eq!(iter.next(), Some(Interface::Text));
307	}
308}