atspi_macros/
lib.rs

1#![deny(clippy::all, clippy::pedantic, clippy::cargo, unsafe_code)]
2#![allow(clippy::too_many_lines)]
3#[cfg(feature = "unstable_atspi_proxy_macro")]
4mod proxy;
5#[cfg(feature = "unstable_atspi_proxy_macro")]
6mod utils;
7#[cfg(feature = "unstable_atspi_proxy_macro")]
8mod zbus_proxy;
9
10#[cfg(feature = "unstable_atspi_proxy_macro")]
11use syn::{AttributeArgs, ItemTrait};
12
13use proc_macro::TokenStream;
14use quote::quote;
15use syn::{parse_macro_input, DeriveInput, Type};
16
17use std::convert::TryFrom;
18
19enum FromZbusMessageParam {
20	Invalid,
21	Body(Type),
22	Member(String),
23}
24
25impl From<(String, String)> for FromZbusMessageParam {
26	fn from(items: (String, String)) -> Self {
27		match (items.0.as_str(), items.1.as_str()) {
28			("body", tp) => Self::Body(
29				syn::parse_str(tp)
30					.expect("The value given to the 'body' parameter must be a valid type."),
31			),
32			("member", mem) => Self::Member(mem.to_string()),
33			_ => Self::Invalid,
34		}
35	}
36}
37
38//
39// Derive macro for that implements TryFrom<Event> on a per name / member basis.
40//
41
42#[proc_macro_derive(TrySignify)]
43pub fn implement_signified(input: TokenStream) -> TokenStream {
44	// Parse the input token stream into a syntax tree
45	let DeriveInput { ident, .. } = parse_macro_input!(input);
46
47	// Extract the name of the struct
48	let name = &ident;
49
50	// Generate the expanded code
51	let expanded = quote! {
52		impl Signified for #name {
53			type Inner = AtspiEvent;
54			fn inner(&self) -> &Self::Inner {
55				&self.0
56			}
57
58			/// Returns `properties`.
59			fn properties(&self) -> &std::collections::HashMap<String, OwnedValue> {
60				self.0.properties()
61			}
62
63			/// Returns `kind` body member.
64			fn kind(&self) -> &str {
65				self.inner().kind()
66			}
67		}
68	};
69
70	// Return the expanded code as a token stream
71	TokenStream::from(expanded)
72}
73
74enum AtspiEventInnerName {
75	Detail1,
76	Detail2,
77	AnyData,
78}
79impl ToString for AtspiEventInnerName {
80	fn to_string(&self) -> String {
81		match self {
82			Self::Detail1 => "detail1",
83			Self::Detail2 => "detail2",
84			Self::AnyData => "any_data",
85		}
86		.to_string()
87	}
88}
89enum ConversionError {
90	FunctionAlreadyCreatedFor,
91	UnknownItem,
92}
93impl TryFrom<usize> for AtspiEventInnerName {
94	type Error = ConversionError;
95
96	fn try_from(from: usize) -> Result<Self, Self::Error> {
97		match from {
98			0 | 4 => Err(ConversionError::FunctionAlreadyCreatedFor),
99			1 => Ok(Self::Detail1),
100			2 => Ok(Self::Detail2),
101			3 => Ok(Self::AnyData),
102			_ => Err(ConversionError::UnknownItem),
103		}
104	}
105}
106
107#[proc_macro_attribute]
108#[cfg(feature = "unstable_atspi_proxy_macro")]
109pub fn atspi_proxy(attr: TokenStream, item: TokenStream) -> TokenStream {
110	let args = parse_macro_input!(attr as AttributeArgs);
111	let input = parse_macro_input!(item as ItemTrait);
112	let zbus_part =
113		zbus_proxy::expand(&args, &input).unwrap_or_else(syn::Error::into_compile_error);
114	let atspi_part = proxy::expand(&input).unwrap_or_else(syn::Error::into_compile_error);
115	quote! {
116	#zbus_part
117	#atspi_part
118		}
119	.into()
120}