1use async_trait::async_trait;
2use atspi_proxies::{
3 accessible::{Accessible, AccessibleBlocking, AccessibleProxy, AccessibleProxyBlocking},
4 action::{Action, ActionBlocking, ActionProxy, ActionProxyBlocking},
5 application::{Application, ApplicationBlocking, ApplicationProxy, ApplicationProxyBlocking},
6 collection::{Collection, CollectionBlocking, CollectionProxy, CollectionProxyBlocking},
7 component::{Component, ComponentBlocking, ComponentProxy, ComponentProxyBlocking},
8 document::{Document, DocumentBlocking, DocumentProxy, DocumentProxyBlocking},
9 editable_text::{
10 EditableText, EditableTextBlocking, EditableTextProxy, EditableTextProxyBlocking,
11 },
12 hyperlink::{Hyperlink, HyperlinkBlocking, HyperlinkProxy, HyperlinkProxyBlocking},
13 hypertext::{Hypertext, HypertextBlocking, HypertextProxy, HypertextProxyBlocking},
14 image::{Image, ImageBlocking, ImageProxy, ImageProxyBlocking},
15 selection::{Selection, SelectionBlocking, SelectionProxy, SelectionProxyBlocking},
16 table::{Table, TableBlocking, TableProxy, TableProxyBlocking},
17 table_cell::{TableCell, TableCellBlocking, TableCellProxy, TableCellProxyBlocking},
18 text::{Text, TextBlocking, TextProxy, TextProxyBlocking},
19 value::{Value, ValueBlocking, ValueProxy, ValueProxyBlocking},
20 AtspiProxy,
21};
22use std::ops::Deref;
23use zbus::{
24 blocking::Proxy as ProxyBlocking, blocking::ProxyBuilder as ProxyBuilderBlocking,
25 CacheProperties, Error, Proxy, ProxyBuilder, ProxyDefault,
26};
27
28#[allow(clippy::module_name_repetitions)]
29#[async_trait]
30pub trait Convertable {
31 type Error: std::error::Error;
32 type Accessible: Accessible + Send + Sync;
33 type Action: Action + Send + Sync;
34 type Application: Application + Send + Sync;
35 type Collection: Collection + Send + Sync;
36 type Component: Component + Send + Sync;
37 type Document: Document + Send + Sync;
38 type Hypertext: Hypertext + Send + Sync;
39 type Hyperlink: Hyperlink + Send + Sync;
40 type Image: Image + Send + Sync;
41 type Selection: Selection + Send + Sync;
42 type Table: Table + Send + Sync;
43 type TableCell: TableCell + Send + Sync;
44 type Text: Text + Send + Sync;
45 type EditableText: EditableText + Send + Sync;
46 type Value: Value + Send + Sync;
47
48 async fn to_accessible(&self) -> Result<Self::Accessible, Self::Error>;
56 async fn to_action(&self) -> Result<Self::Action, Self::Error>;
62 async fn to_application(&self) -> Result<Self::Application, Self::Error>;
68 async fn to_collection(&self) -> Result<Self::Collection, Self::Error>;
74 async fn to_component(&self) -> Result<Self::Component, Self::Error>;
80 async fn to_document(&self) -> Result<Self::Document, Self::Error>;
81 async fn to_hypertext(&self) -> Result<Self::Hypertext, Self::Error>;
82 async fn to_hyperlink(&self) -> Result<Self::Hyperlink, Self::Error>;
83 async fn to_image(&self) -> Result<Self::Image, Self::Error>;
84 async fn to_selection(&self) -> Result<Self::Selection, Self::Error>;
85 async fn to_table(&self) -> Result<Self::Table, Self::Error>;
86 async fn to_table_cell(&self) -> Result<Self::TableCell, Self::Error>;
87 async fn to_text(&self) -> Result<Self::Text, Self::Error>;
88 async fn to_editable_text(&self) -> Result<Self::EditableText, Self::Error>;
89 async fn to_value(&self) -> Result<Self::Value, Self::Error>;
90}
91
92#[allow(clippy::module_name_repetitions)]
93pub trait ConvertableBlocking {
94 type Error: std::error::Error;
95 type Accessible: AccessibleBlocking;
96 type Action: ActionBlocking;
97 type Application: ApplicationBlocking;
98 type Collection: CollectionBlocking;
99 type Component: ComponentBlocking;
100 type Document: DocumentBlocking;
101 type Hypertext: HypertextBlocking;
102 type Hyperlink: HyperlinkBlocking;
103 type Image: ImageBlocking;
104 type Selection: SelectionBlocking;
105 type Table: TableBlocking;
106 type TableCell: TableCellBlocking;
107 type Text: TextBlocking;
108 type EditableText: EditableTextBlocking;
109 type Value: ValueBlocking;
110
111 fn to_accessible(&self) -> Result<Self::Accessible, Self::Error>;
119 fn to_action(&self) -> Result<Self::Action, Self::Error>;
125 fn to_application(&self) -> Result<Self::Application, Self::Error>;
131 fn to_collection(&self) -> Result<Self::Collection, Self::Error>;
137 fn to_component(&self) -> Result<Self::Component, Self::Error>;
143 fn to_document(&self) -> Result<Self::Document, Self::Error>;
149 fn to_hypertext(&self) -> Result<Self::Hypertext, Self::Error>;
155 fn to_hyperlink(&self) -> Result<Self::Hyperlink, Self::Error>;
161 fn to_image(&self) -> Result<Self::Image, Self::Error>;
167 fn to_selection(&self) -> Result<Self::Selection, Self::Error>;
173 fn to_table(&self) -> Result<Self::Table, Self::Error>;
179 fn to_table_cell(&self) -> Result<Self::TableCell, Self::Error>;
185 fn to_text(&self) -> Result<Self::Text, Self::Error>;
191 fn to_editable_text(&self) -> Result<Self::EditableText, Self::Error>;
197 fn to_value(&self) -> Result<Self::Value, Self::Error>;
203}
204
205#[inline]
206async fn convert_to_new_type<
207 'a,
208 'b,
209 T: From<Proxy<'b>> + ProxyDefault + AtspiProxy,
210 U: Deref<Target = Proxy<'a>> + ProxyDefault + AtspiProxy,
211>(
212 from: &U,
213) -> zbus::Result<T> {
214 let accessible = AccessibleProxy::builder(from.connection())
216 .destination(from.destination())?
217 .cache_properties(CacheProperties::No)
218 .path(from.path())?
219 .build()
220 .await?;
221 if !accessible
223 .get_interfaces()
224 .await?
225 .contains(<T as AtspiProxy>::INTERFACE)
226 {
227 return Err(Error::InterfaceNotFound);
228 }
229 let path = from.path().to_owned();
231 let dest = from.destination().to_owned();
232 ProxyBuilder::<'b, T>::new_bare(from.connection())
233 .interface(<T as ProxyDefault>::INTERFACE)?
234 .destination(dest)?
235 .cache_properties(CacheProperties::No)
236 .path(path)?
237 .build()
238 .await
239}
240
241#[inline]
242fn convert_to_new_type_blocking<
243 'a,
244 'b,
245 T: From<Proxy<'b>> + ProxyDefault + AtspiProxy,
246 U: Deref<Target = ProxyBlocking<'a>> + ProxyDefault,
247>(
248 from: &U,
249) -> zbus::Result<T> {
250 let accessible = AccessibleProxyBlocking::builder(from.connection())
252 .destination(from.destination())?
253 .cache_properties(CacheProperties::No)
254 .path(from.path())?
255 .build()?;
256 if !accessible.get_interfaces()?.contains(<T as AtspiProxy>::INTERFACE) {
258 return Err(Error::InterfaceNotFound);
259 }
260 let path = from.path().to_owned();
262 let dest = from.destination().to_owned();
263 ProxyBuilderBlocking::<'b, T>::new_bare(from.connection())
264 .interface(<T as ProxyDefault>::INTERFACE)?
265 .destination(dest)?
266 .cache_properties(CacheProperties::No)
267 .path(path)?
268 .build()
269}
270
271#[async_trait]
272impl<'a, T: Deref<Target = Proxy<'a>> + ProxyDefault + AtspiProxy + Sync> Convertable for T {
273 type Error = zbus::Error;
274 type Accessible = AccessibleProxy<'a>;
275 type Action = ActionProxy<'a>;
276 type Application = ApplicationProxy<'a>;
277 type Collection = CollectionProxy<'a>;
278 type Component = ComponentProxy<'a>;
279 type Document = DocumentProxy<'a>;
280 type Hypertext = HypertextProxy<'a>;
281 type Hyperlink = HyperlinkProxy<'a>;
282 type Image = ImageProxy<'a>;
283 type Selection = SelectionProxy<'a>;
284 type Table = TableProxy<'a>;
285 type TableCell = TableCellProxy<'a>;
286 type Text = TextProxy<'a>;
287 type EditableText = EditableTextProxy<'a>;
288 type Value = ValueProxy<'a>;
289 async fn to_accessible(&self) -> zbus::Result<Self::Accessible> {
291 convert_to_new_type(self).await
292 }
293 async fn to_action(&self) -> zbus::Result<Self::Action> {
294 convert_to_new_type(self).await
295 }
296 async fn to_application(&self) -> zbus::Result<Self::Application> {
297 convert_to_new_type(self).await
298 }
299 async fn to_collection(&self) -> zbus::Result<Self::Collection> {
300 convert_to_new_type(self).await
301 }
302 async fn to_component(&self) -> zbus::Result<Self::Component> {
303 convert_to_new_type(self).await
304 }
305 async fn to_document(&self) -> zbus::Result<Self::Document> {
306 convert_to_new_type(self).await
307 }
308 async fn to_hypertext(&self) -> zbus::Result<Self::Hypertext> {
309 convert_to_new_type(self).await
310 }
311 async fn to_hyperlink(&self) -> zbus::Result<Self::Hyperlink> {
312 convert_to_new_type(self).await
313 }
314 async fn to_image(&self) -> zbus::Result<Self::Image> {
315 convert_to_new_type(self).await
316 }
317 async fn to_selection(&self) -> zbus::Result<Self::Selection> {
318 convert_to_new_type(self).await
319 }
320 async fn to_table(&self) -> zbus::Result<Self::Table> {
321 convert_to_new_type(self).await
322 }
323 async fn to_table_cell(&self) -> zbus::Result<Self::TableCell> {
324 convert_to_new_type(self).await
325 }
326 async fn to_text(&self) -> zbus::Result<Self::Text> {
327 convert_to_new_type(self).await
328 }
329 async fn to_editable_text(&self) -> zbus::Result<Self::EditableText> {
330 convert_to_new_type(self).await
331 }
332 async fn to_value(&self) -> zbus::Result<Self::Value> {
333 convert_to_new_type(self).await
334 }
335}
336
337impl<'a, T: Deref<Target = ProxyBlocking<'a>> + ProxyDefault + AtspiProxy> ConvertableBlocking
338 for T
339{
340 type Error = zbus::Error;
341 type Accessible = AccessibleProxyBlocking<'a>;
342 type Action = ActionProxyBlocking<'a>;
343 type Application = ApplicationProxyBlocking<'a>;
344 type Collection = CollectionProxyBlocking<'a>;
345 type Component = ComponentProxyBlocking<'a>;
346 type Document = DocumentProxyBlocking<'a>;
347 type Hypertext = HypertextProxyBlocking<'a>;
348 type Hyperlink = HyperlinkProxyBlocking<'a>;
349 type Image = ImageProxyBlocking<'a>;
350 type Selection = SelectionProxyBlocking<'a>;
351 type Table = TableProxyBlocking<'a>;
352 type TableCell = TableCellProxyBlocking<'a>;
353 type Text = TextProxyBlocking<'a>;
354 type EditableText = EditableTextProxyBlocking<'a>;
355 type Value = ValueProxyBlocking<'a>;
356 fn to_accessible(&self) -> zbus::Result<Self::Accessible> {
358 convert_to_new_type_blocking(self)
359 }
360 fn to_action(&self) -> zbus::Result<Self::Action> {
361 convert_to_new_type_blocking(self)
362 }
363 fn to_application(&self) -> zbus::Result<Self::Application> {
364 convert_to_new_type_blocking(self)
365 }
366 fn to_collection(&self) -> zbus::Result<Self::Collection> {
367 convert_to_new_type_blocking(self)
368 }
369 fn to_component(&self) -> zbus::Result<Self::Component> {
370 convert_to_new_type_blocking(self)
371 }
372 fn to_document(&self) -> zbus::Result<Self::Document> {
373 convert_to_new_type_blocking(self)
374 }
375 fn to_hypertext(&self) -> zbus::Result<Self::Hypertext> {
376 convert_to_new_type_blocking(self)
377 }
378 fn to_hyperlink(&self) -> zbus::Result<Self::Hyperlink> {
379 convert_to_new_type_blocking(self)
380 }
381 fn to_image(&self) -> zbus::Result<Self::Image> {
382 convert_to_new_type_blocking(self)
383 }
384 fn to_selection(&self) -> zbus::Result<Self::Selection> {
385 convert_to_new_type_blocking(self)
386 }
387 fn to_table(&self) -> zbus::Result<Self::Table> {
388 convert_to_new_type_blocking(self)
389 }
390 fn to_table_cell(&self) -> zbus::Result<Self::TableCell> {
391 convert_to_new_type_blocking(self)
392 }
393 fn to_text(&self) -> zbus::Result<Self::Text> {
394 convert_to_new_type_blocking(self)
395 }
396 fn to_editable_text(&self) -> zbus::Result<Self::EditableText> {
397 convert_to_new_type_blocking(self)
398 }
399 fn to_value(&self) -> zbus::Result<Self::Value> {
400 convert_to_new_type_blocking(self)
401 }
402}