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	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}