1macro_rules! impl_event_properties {
21 ($type:ty) => {
22 impl EventProperties for $type {
23 fn sender(&self) -> UniqueName<'_> {
24 self.item.name.as_ref()
25 }
26 fn path(&self) -> ObjectPath<'_> {
27 self.item.path.as_ref()
28 }
29 }
30 };
31}
32
33macro_rules! impl_from_interface_event_enum_for_event {
49 ($outer_type:ty, $outer_variant:path) => {
50 impl From<$outer_type> for Event {
51 fn from(event_variant: $outer_type) -> Event {
52 $outer_variant(event_variant.into())
53 }
54 }
55 };
56}
57
58macro_rules! impl_try_from_event_for_user_facing_event_type {
79 ($outer_type:ty, $outer_variant:path) => {
80 impl TryFrom<Event> for $outer_type {
81 type Error = AtspiError;
82 fn try_from(generic_event: Event) -> Result<$outer_type, Self::Error> {
83 if let $outer_variant(event_type) = generic_event {
84 Ok(event_type)
85 } else {
86 Err(AtspiError::Conversion("Invalid type"))
87 }
88 }
89 }
90 };
91}
92
93macro_rules! impl_from_user_facing_event_for_interface_event_enum {
110 ($inner_type:ty, $outer_type:ty, $inner_variant:path) => {
111 impl From<$inner_type> for $outer_type {
112 fn from(specific_event: $inner_type) -> $outer_type {
113 $inner_variant(specific_event)
114 }
115 }
116 };
117}
118
119macro_rules! impl_from_user_facing_type_for_event_enum {
139 ($inner_type:ty, $outer_variant:path) => {
140 impl From<$inner_type> for Event {
141 fn from(event_variant: $inner_type) -> Event {
142 $outer_variant(event_variant.into())
143 }
144 }
145 };
146}
147
148macro_rules! impl_try_from_event_for_user_facing_type {
171 ($inner_type:ty, $inner_variant:path, $outer_variant:path) => {
172 impl TryFrom<Event> for $inner_type {
173 type Error = AtspiError;
174 fn try_from(generic_event: Event) -> Result<$inner_type, Self::Error> {
175 if let $outer_variant($inner_variant(specific_event)) = generic_event {
176 Ok(specific_event)
177 } else {
178 Err(AtspiError::Conversion("Invalid type"))
179 }
180 }
181 }
182 };
183}
184
185macro_rules! impl_to_dbus_message {
209 ($type:ty) => {
210 #[cfg(feature = "zbus")]
211 impl TryFrom<$type> for zbus::Message {
212 type Error = AtspiError;
213 fn try_from(event: $type) -> Result<Self, Self::Error> {
214 Ok(zbus::Message::signal(
215 event.path(),
216 <$type as BusProperties>::DBUS_INTERFACE,
217 <$type as BusProperties>::DBUS_MEMBER,
218 )?
219 .sender(event.sender().to_string())?
220 .build(&event.body())?)
221 }
222 }
223 };
224}
225
226macro_rules! impl_from_dbus_message {
254 ($type:ty) => {
255 #[cfg(feature = "zbus")]
256 impl TryFrom<&zbus::Message> for $type {
257 type Error = AtspiError;
258 fn try_from(msg: &zbus::Message) -> Result<Self, Self::Error> {
259 let header = msg.header();
260 if header.interface().ok_or(AtspiError::MissingInterface)?
261 != <$type as BusProperties>::DBUS_INTERFACE
262 {
263 return Err(AtspiError::InterfaceMatch(format!(
264 "The interface {} does not match the signal's interface: {}",
265 header.interface().unwrap(),
266 <$type as BusProperties>::DBUS_INTERFACE
267 )));
268 }
269 if header.member().ok_or(AtspiError::MissingMember)? != <$type>::DBUS_MEMBER {
270 return Err(AtspiError::MemberMatch(format!(
271 "The member {} does not match the signal's member: {}",
272 header.member().unwrap(),
274 <$type as BusProperties>::DBUS_MEMBER
275 )));
276 }
277 <$type>::from_message_parts(
278 msg.try_into()?,
279 msg.body().deserialize::<<$type as BusProperties>::Body>()?,
280 )
281 }
282 }
283 };
284}
285
286#[cfg(test)]
298macro_rules! generic_event_test_case {
299 ($type:ty) => {
300 #[test]
301 fn generic_event_uses() {
302 let struct_event = <$type>::default();
303 assert_eq!(struct_event.path().as_str(), "/org/a11y/atspi/accessible/null");
304 assert_eq!(struct_event.sender().as_str(), ":0.0");
305 let item = struct_event.item.clone();
306 let body = struct_event.body();
307 let build_struct = <$type>::from_message_parts(item, body)
308 .expect("<$type as Default>'s parts should build a valid ObjectRef");
309 assert_eq!(struct_event, build_struct);
310 }
311 };
312}
313
314#[cfg(test)]
325macro_rules! event_enum_test_case {
326 ($type:ty) => {
327 #[test]
328 fn event_enum_conversion() {
329 let struct_event = <$type>::default();
330 let event = Event::from(struct_event.clone());
331 let struct_event_back = <$type>::try_from(event)
332 .expect("Should convert event enum into specific event type because it was created from it. Check the `impl_from_interface_event_enum_for_event` macro");
333 assert_eq!(struct_event, struct_event_back);
334 }
335 };
336}
337
338#[cfg(test)]
354macro_rules! event_enum_transparency_test_case {
355 ($type:ty) => {
356 #[test]
357 fn event_enum_transparency_test_case() {
358 let specific_event = <$type>::default();
359 let generic_event = Event::from(specific_event.clone());
360 assert_eq!(
361 specific_event.member(),
362 generic_event.member(),
363 "DBus member strings do not match."
364 );
365 assert_eq!(
366 specific_event.interface(),
367 generic_event.interface(),
368 "Registry interfaces do not match."
369 );
370 assert_eq!(
371 specific_event.registry_string(),
372 generic_event.registry_string(),
373 "Registry strings do not match."
374 );
375 assert_eq!(
376 specific_event.match_rule(),
377 generic_event.match_rule(),
378 "Match rule strings do not match."
379 );
380 assert_eq!(specific_event.path(), generic_event.path(), "Pathsdo not match.");
381 assert_eq!(specific_event.sender(), generic_event.sender(), "Senders do not match.");
382 }
383 };
384}
385
386#[cfg(test)]
392macro_rules! zbus_message_test_case {
393 ($type:ty) => {
394 #[cfg(feature = "zbus")]
395 #[test]
396 fn zbus_msg_conversion_to_specific_event_type() {
397 let struct_event = <$type>::default();
398 let msg: zbus::Message = zbus::Message::try_from(struct_event.clone())
399 .expect("Should convert a `$type::default()` into a message. Check the `impl_to_dbus_message` macro .");
400 let struct_event_back =
401 <$type>::try_from(&msg).expect("Should convert from `$type::default()` originated `Message` back into a specific event type. Check the `impl_from_dbus_message` macro.");
402 assert_eq!(struct_event, struct_event_back);
403 }
404
405 #[cfg(feature = "zbus")]
406 #[test]
407 fn zbus_msg_conversion_to_event_enum_type() {
408 let struct_event = <$type>::default();
409 let msg: zbus::Message = zbus::Message::try_from(struct_event.clone()).expect("Should convert a `$type::default()` into a message. Check the `impl_to_dbus_message` macro .");
410 let event_enum_back =
411 Event::try_from(&msg).expect("Should convert a from `$type::default()` built `Message` into an event enum. Check the `impl_from_dbus_message` macro .");
412 let event_enum: Event = struct_event.into();
413 assert_eq!(event_enum, event_enum_back);
414 }
415 #[cfg(feature = "zbus")]
418 #[test]
419 #[should_panic(expected = "Should panic")]
420 fn zbus_msg_conversion_failure_fake_msg() -> () {
421 let fake_msg = zbus::Message::signal(
422 "/org/a11y/sixtynine/fourtwenty",
423 "org.a11y.atspi.technically.valid",
424 "MadeUpMember",
425 )
426 .unwrap()
427 .sender(":0.0")
428 .unwrap()
429 .build(&())
430 .unwrap();
431 let event = <$type>::try_from(&fake_msg);
432 event.expect("Should panic");
433 }
434
435 #[cfg(feature = "zbus")]
436 #[test]
437 #[should_panic(expected = "Should panic")]
438 fn zbus_msg_conversion_failure_correct_interface() -> () {
439 let fake_msg = zbus::Message::signal(
440 "/org/a11y/sixtynine/fourtwenty",
441 <$type as BusProperties>::DBUS_INTERFACE,
442 "MadeUpMember",
443 )
444 .unwrap()
445 .sender(":0.0")
446 .unwrap()
447 .build(&())
448 .unwrap();
449 let event = <$type>::try_from(&fake_msg);
450 event.expect("Should panic");
451 }
452
453 #[cfg(feature = "zbus")]
454 #[test]
455 #[should_panic(expected = "Should panic")]
456 fn zbus_msg_conversion_failure_correct_interface_and_member() -> () {
457 let fake_msg = zbus::Message::signal(
458 "/org/a11y/sixtynine/fourtwenty",
459 <$type as BusProperties>::DBUS_INTERFACE,
460 <$type as BusProperties>::DBUS_MEMBER,
461 )
462 .unwrap()
463 .sender(":0.0")
464 .unwrap()
465 .build(&())
466 .unwrap();
467 let event = <$type>::try_from(&fake_msg);
468 event.expect("Should panic");
469 }
470
471 #[cfg(feature = "zbus")]
472 #[test]
473 #[should_panic(expected = "Should panic")]
474 fn zbus_msg_conversion_failure_correct_body() -> () {
475 let fake_msg = zbus::Message::signal(
476 "/org/a11y/sixtynine/fourtwenty",
477 "org.a11y.atspi.accessible.technically.valid",
478 "FakeMember",
479 )
480 .unwrap()
481 .sender(":0.0")
482 .unwrap()
483 .build(&<$type>::default().body())
484 .unwrap();
485 let event = <$type>::try_from(&fake_msg);
486 event.expect("Should panic");
487 }
488
489 #[cfg(feature = "zbus")]
490 #[test]
491 #[should_panic(expected = "Should panic")]
492 fn zbus_msg_conversion_failure_correct_body_and_member() -> () {
493 let fake_msg = zbus::Message::signal(
494 "/org/a11y/sixtynine/fourtwenty",
495 "org.a11y.atspi.accessible.technically.valid",
496 <$type as BusProperties>::DBUS_MEMBER,
497 )
498 .unwrap()
499 .sender(":0.0")
500 .unwrap()
501 .build(&<$type>::default().body())
502 .unwrap();
503 let event = <$type>::try_from(&fake_msg);
504 event.expect("Should panic");
505 }
506 };
507}
508
509macro_rules! event_wrapper_test_cases {
528 ($type:ty, $any_subtype:ty) => {
529 #[cfg(test)]
530 #[rename_item::rename(name($type), prefix = "events_tests_", case = "snake")]
531 mod foo {
532 use super::{$any_subtype, $type, Event, BusProperties};
533 #[test]
534 fn into_and_try_from_event() {
535 let sub_type = <$any_subtype>::default();
537 let mod_type = <$type>::from(sub_type);
539 let event = Event::from(mod_type.clone());
541 let mod_type2 = <$type>::try_from(event.clone())
543 .expect("Should convert outer `Event` enum into interface enum because it was created from it. Check the `impl_try_from_event_for_user_facing_event_type` macro");
544 assert_eq!(
545 mod_type, mod_type2,
546 "Events were able to be parsed and encapsulated, but they have changed value"
547 );
548 }
549 #[cfg(feature = "zbus")]
550 #[test]
551 #[should_panic(expected = "Should panic")]
552 fn zbus_msg_invalid_interface() {
553 let fake_msg = zbus::Message::signal(
554 "/org/a11y/sixtynine/fourtwenty",
555 "org.a11y.atspi.technically.valid.lol",
556 <$any_subtype as BusProperties>::DBUS_MEMBER,
557 )
558 .unwrap()
559 .sender(":0.0")
560 .unwrap()
561 .build(&<$any_subtype>::default().body())
562 .unwrap();
563
564 let mod_type = <$type>::try_from(&fake_msg);
573 mod_type.expect("Should panic");
574 }
575 #[cfg(feature = "zbus")]
576 #[test]
577 #[should_panic(expected = "Should panic")]
578 fn zbus_msg_invalid_member() {
579 let fake_msg = zbus::Message::signal(
580 "/org/a11y/sixtynine/fourtwenty",
581 <$any_subtype as BusProperties>::DBUS_INTERFACE,
582 "FakeFunctionLol",
583 )
584 .unwrap()
585 .sender(":0.0")
586 .unwrap()
587 .build(&<$any_subtype>::default().body())
588 .unwrap();
589 let mod_type = <$type>::try_from(&fake_msg);
591 mod_type.expect("Should panic");
592 }
593 #[cfg(feature = "zbus")]
594 #[test]
595 #[should_panic(expected = "Should panic")]
596 fn zbus_msg_invalid_member_and_interface() {
597 let fake_msg = zbus::Message::signal(
598 "/org/a11y/sixtynine/fourtwenty",
599 "org.a11y.atspi.technically.allowed",
600 "FakeFunctionLol",
601 )
602 .unwrap()
603 .sender(":0.0")
604 .unwrap()
605 .build(&<$any_subtype>::default().body())
606 .unwrap();
607 let mod_type = <$type>::try_from(&fake_msg);
609
610 mod_type.expect("Should panic");
612 }
613 #[cfg(feature = "zbus")]
614 #[test]
615 fn zbus_msg_conversion() {
616 let valid_msg = zbus::Message::signal(
617 "/org/a11y/sixtynine/fourtwenty",
618 <$any_subtype as BusProperties>::DBUS_INTERFACE,
619 <$any_subtype as BusProperties>::DBUS_MEMBER,
620 )
621 .unwrap()
622 .sender(":0.0")
623 .unwrap()
624 .build(&<$any_subtype>::default().body())
625 .unwrap();
626 let mod_type = <$type>::try_from(&valid_msg);
628 mod_type.expect("Should convert from `$any_subtype::default()` built `Message` back into a interface event enum variant wrapping an inner type. Check the `impl_from_dbus_message` macro.");
629 }
630 }
631 };
632}
633
634macro_rules! event_test_cases {
635 ($type:ty) => {
636 #[cfg(test)]
637 #[rename_item::rename(name($type), prefix = "event_tests_", case = "snake")]
638 mod foo {
639 use super::{$type, Event, BusProperties, EventProperties, EventTypeProperties};
640
641 generic_event_test_case!($type);
642 event_enum_test_case!($type);
643 zbus_message_test_case!($type);
644 event_enum_transparency_test_case!($type);
645 }
646 assert_impl_all!(
647 $type: Clone,
648 std::fmt::Debug,
649 serde::Serialize,
650 serde::Deserialize<'static>,
651 Default,
652 PartialEq,
653 Eq,
654 std::hash::Hash,
655 crate::EventProperties,
656 crate::EventTypeProperties,
657 crate::BusProperties,
658 );
659 #[cfg(feature = "zbus")]
660 assert_impl_all!(zbus::Message: TryFrom<$type>);
661 };
662}