atspi_proxies/
proxy_ext.rs

1use crate::{
2	accessible::AccessibleProxy, action::ActionProxy, application::ApplicationProxy,
3	cache::CacheProxy, collection::CollectionProxy, component::ComponentProxy,
4	document::DocumentProxy, editable_text::EditableTextProxy, hyperlink::HyperlinkProxy,
5	hypertext::HypertextProxy, image::ImageProxy, selection::SelectionProxy, table::TableProxy,
6	table_cell::TableCellProxy, text::TextProxy, value::ValueProxy, AtspiError,
7};
8use atspi_common::{Interface, InterfaceSet, Result};
9
10/// Easily acquire the other interface proxies an object may have.
11///
12/// Equip objects with conversions to proxies of the objects' further implemented interfaces
13/// by extending `AccessibleProxy`.
14///
15/// The `proxies` method returns a `Proxies` struct, which contains lazily loaded proxy accessors.
16///
17/// # Lazy initialization and cheap checks
18///
19/// Proxies are lazily initialized, so they are only created when requested.
20/// Interface availability is checked before creating the proxy and is a cheap bitop.
21pub trait ProxyExt<'a> {
22	/// Get `Proxies` for the current object.
23	fn proxies(&self) -> impl std::future::Future<Output = Result<Proxies<'a>>>;
24}
25
26/// An object for safe conversion to the related interface proxies.
27#[derive(Clone, Debug)]
28pub struct Proxies<'a> {
29	interfaces: InterfaceSet,
30	proxy: zbus::Proxy<'a>,
31	inner: InnerProxies<'a>,
32}
33
34#[derive(Clone, Debug, Default)]
35struct InnerProxies<'a> {
36	action: Option<ActionProxy<'a>>,
37	application: Option<ApplicationProxy<'a>>,
38	cache: Option<CacheProxy<'a>>,
39	collection: Option<CollectionProxy<'a>>,
40	component: Option<ComponentProxy<'a>>,
41	document: Option<DocumentProxy<'a>>,
42	editable_text: Option<EditableTextProxy<'a>>,
43	hyperlink: Option<HyperlinkProxy<'a>>,
44	hypertext: Option<HypertextProxy<'a>>,
45	image: Option<ImageProxy<'a>>,
46	selection: Option<SelectionProxy<'a>>,
47	table: Option<TableProxy<'a>>,
48	table_cell: Option<TableCellProxy<'a>>,
49	text: Option<TextProxy<'a>>,
50	value: Option<ValueProxy<'a>>,
51}
52
53impl<'a> ProxyExt<'a> for AccessibleProxy<'a> {
54	async fn proxies(&self) -> Result<Proxies<'a>> {
55		let iface_set: InterfaceSet = self.get_interfaces().await?;
56		let proxy = self.inner().clone();
57
58		Ok(Proxies { interfaces: iface_set, proxy, inner: InnerProxies::default() })
59	}
60}
61
62impl<'a> Proxies<'a> {
63	/// Get the `Action` interface proxy.
64	///
65	/// # Errors
66	///
67	/// Returns an error if the interface is not available.
68	pub fn action(&mut self) -> Result<&mut ActionProxy<'a>> {
69		if self.interfaces.contains(Interface::Action) {
70			let proxy_ref = self
71				.inner
72				.action
73				.get_or_insert_with(|| ActionProxy::from(self.proxy.clone()));
74			Ok(proxy_ref)
75		} else {
76			Err(AtspiError::InterfaceNotAvailable("Action"))
77		}
78	}
79
80	/// Get the `Application` interface proxy.
81	///
82	/// # Errors
83	///
84	/// Returns an error if the interface is not available.
85	pub fn application(&mut self) -> Result<&mut ApplicationProxy<'a>> {
86		if self.interfaces.contains(Interface::Application) {
87			let proxy_ref = self
88				.inner
89				.application
90				.get_or_insert_with(|| ApplicationProxy::from(self.proxy.clone()));
91			Ok(proxy_ref)
92		} else {
93			Err(AtspiError::InterfaceNotAvailable("Application"))
94		}
95	}
96
97	/// Get the `Cache` interface proxy.
98	///
99	/// # Errors
100	///
101	/// Returns an error if the interface is not available.
102	pub fn cache(&mut self) -> Result<&mut CacheProxy<'a>> {
103		if self.interfaces.contains(Interface::Cache) {
104			let proxy_ref = self
105				.inner
106				.cache
107				.get_or_insert_with(|| CacheProxy::from(self.proxy.clone()));
108			Ok(proxy_ref)
109		} else {
110			Err(AtspiError::InterfaceNotAvailable("Cache"))
111		}
112	}
113
114	/// Get the `Collection` interface proxy.
115	///
116	/// # Errors
117	///
118	/// Returns an error if the interface is not available.
119	pub fn collection(&mut self) -> Result<&mut CollectionProxy<'a>> {
120		if self.interfaces.contains(Interface::Collection) {
121			let proxy_ref = self
122				.inner
123				.collection
124				.get_or_insert_with(|| CollectionProxy::from(self.proxy.clone()));
125			Ok(proxy_ref)
126		} else {
127			Err(AtspiError::InterfaceNotAvailable("Collection"))
128		}
129	}
130
131	/// Get the `Component` interface proxy.
132	///
133	/// # Errors
134	///
135	/// Returns an error if the interface is not available.
136	pub fn component(&mut self) -> Result<&mut ComponentProxy<'a>> {
137		if self.interfaces.contains(Interface::Component) {
138			let proxy_ref = self
139				.inner
140				.component
141				.get_or_insert_with(|| ComponentProxy::from(self.proxy.clone()));
142			Ok(proxy_ref)
143		} else {
144			Err(AtspiError::InterfaceNotAvailable("Component"))
145		}
146	}
147
148	/// Get the `Document` interface proxy.
149	///
150	/// # Errors
151	///
152	/// Returns an error if the interface is not available.
153	pub fn document(&mut self) -> Result<&mut DocumentProxy<'a>> {
154		if self.interfaces.contains(Interface::Document) {
155			let proxy_ref = self
156				.inner
157				.document
158				.get_or_insert_with(|| DocumentProxy::from(self.proxy.clone()));
159			Ok(proxy_ref)
160		} else {
161			Err(AtspiError::InterfaceNotAvailable("Document"))
162		}
163	}
164
165	/// Get the `EditableText` interface proxy.
166	///
167	/// # Errors
168	///
169	/// Returns an error if the interface is not available.
170	pub fn editable_text(&mut self) -> Result<&mut EditableTextProxy<'a>> {
171		if self.interfaces.contains(Interface::EditableText) {
172			let proxy_ref = self
173				.inner
174				.editable_text
175				.get_or_insert_with(|| EditableTextProxy::from(self.proxy.clone()));
176			Ok(proxy_ref)
177		} else {
178			Err(AtspiError::InterfaceNotAvailable("EditableText"))
179		}
180	}
181
182	/// Get the `Hyperlink` interface proxy.
183	///
184	/// # Errors
185	///
186	/// Returns an error if the interface is not available.
187	pub fn hyperlink(&mut self) -> Result<&mut HyperlinkProxy<'a>> {
188		if self.interfaces.contains(Interface::Hyperlink) {
189			let proxy_ref = self
190				.inner
191				.hyperlink
192				.get_or_insert_with(|| HyperlinkProxy::from(self.proxy.clone()));
193			Ok(proxy_ref)
194		} else {
195			Err(AtspiError::InterfaceNotAvailable("Hyperlink"))
196		}
197	}
198
199	/// Get the `Hypertext` interface proxy.
200	///
201	/// # Errors
202	///
203	/// Returns an error if the interface is not available.
204	pub fn hypertext(&mut self) -> Result<&mut HypertextProxy<'a>> {
205		if self.interfaces.contains(Interface::Hypertext) {
206			let proxy_ref = self
207				.inner
208				.hypertext
209				.get_or_insert_with(|| HypertextProxy::from(self.proxy.clone()));
210			Ok(proxy_ref)
211		} else {
212			Err(AtspiError::InterfaceNotAvailable("Hypertext"))
213		}
214	}
215
216	/// Get the `Image` interface proxy.
217	///
218	/// # Errors
219	///
220	/// Returns an error if the interface is not available.
221	pub fn image(&mut self) -> Result<&mut ImageProxy<'a>> {
222		if self.interfaces.contains(Interface::Image) {
223			let proxy_ref = self
224				.inner
225				.image
226				.get_or_insert_with(|| ImageProxy::from(self.proxy.clone()));
227			Ok(proxy_ref)
228		} else {
229			Err(AtspiError::InterfaceNotAvailable("Image"))
230		}
231	}
232
233	/// Get the `Registry` interface proxy.
234	///
235	/// # Errors
236	///
237	/// Returns an error if the interface is not available.
238	pub fn selection(&mut self) -> Result<&mut SelectionProxy<'a>> {
239		if self.interfaces.contains(Interface::Selection) {
240			let proxy_ref = self
241				.inner
242				.selection
243				.get_or_insert_with(|| SelectionProxy::from(self.proxy.clone()));
244			Ok(proxy_ref)
245		} else {
246			Err(AtspiError::InterfaceNotAvailable("Selection"))
247		}
248	}
249
250	/// Get the `Table` interface proxy.
251	///
252	/// # Errors
253	///
254	/// Returns an error if the interface is not available.
255	pub fn table(&mut self) -> Result<&mut TableProxy<'a>> {
256		if self.interfaces.contains(Interface::Table) {
257			let proxy_ref = self
258				.inner
259				.table
260				.get_or_insert_with(|| TableProxy::from(self.proxy.clone()));
261			Ok(proxy_ref)
262		} else {
263			Err(AtspiError::InterfaceNotAvailable("Table"))
264		}
265	}
266
267	/// Get the `TableCell` interface proxy.
268	///
269	/// # Errors
270	///
271	/// Returns an error if the interface is not available.
272	pub fn table_cell(&mut self) -> Result<&mut TableCellProxy<'a>> {
273		if self.interfaces.contains(Interface::TableCell) {
274			let proxy_ref = self
275				.inner
276				.table_cell
277				.get_or_insert_with(|| TableCellProxy::from(self.proxy.clone()));
278			Ok(proxy_ref)
279		} else {
280			Err(AtspiError::InterfaceNotAvailable("TableCell"))
281		}
282	}
283
284	/// Get the `Text` interface proxy.
285	///
286	/// # Errors
287	///
288	/// Returns an error if the interface is not available.
289	pub fn text(&mut self) -> Result<&mut TextProxy<'a>> {
290		if self.interfaces.contains(Interface::Text) {
291			let proxy_ref = self
292				.inner
293				.text
294				.get_or_insert_with(|| TextProxy::from(self.proxy.clone()));
295			Ok(proxy_ref)
296		} else {
297			Err(AtspiError::InterfaceNotAvailable("Text"))
298		}
299	}
300
301	/// Get the `Value` interface proxy.
302	///
303	/// # Errors
304	///
305	/// Returns an error if the interface is not available.
306	pub fn value(&mut self) -> Result<&mut ValueProxy<'a>> {
307		if self.interfaces.contains(Interface::Value) {
308			let proxy_ref = self
309				.inner
310				.value
311				.get_or_insert_with(|| ValueProxy::from(self.proxy.clone()));
312			Ok(proxy_ref)
313		} else {
314			Err(AtspiError::InterfaceNotAvailable("Value"))
315		}
316	}
317}