atspi_common/events/
event_body.rs

1use crate::AtspiError;
2use serde::{
3	ser::{SerializeMap, SerializeTuple},
4	Deserialize, Serialize,
5};
6use zbus_lockstep_macros::validate;
7use zvariant::{ObjectPath, OwnedValue, Type, Value};
8
9/// Event body as used exclusively by 'Qt' toolkit.
10///
11/// Signature:  "siiv(so)"
12#[derive(Debug, Serialize, Deserialize, PartialEq, Type)]
13pub struct EventBodyQtOwned {
14	/// kind variant, used for specifying an event triple "object:state-changed:focused",
15	/// the "focus" part of this event is what is contained within the kind.
16	#[serde(rename = "type")]
17	pub kind: String,
18
19	/// Generic detail1 value described by AT-SPI.
20	pub detail1: i32,
21
22	/// Generic detail2 value described by AT-SPI.
23	pub detail2: i32,
24
25	/// Generic `any_data` value described by AT-SPI.
26	/// This can be any type.
27	pub any_data: OwnedValue,
28
29	/// Not in use.
30	/// See: [`QtProperties`].
31	#[serde(skip_deserializing)]
32	pub(crate) properties: QtProperties,
33}
34
35impl Clone for EventBodyQtOwned {
36	/// # Safety
37	///
38	/// This implementation of [`Clone`] *can panic!* although chances are slim.
39	///
40	/// If the following conditions are met:
41	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
42	/// 2. the maximum number of open files for the process is exceeded.
43	///
44	/// Then this function panic.
45	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
46	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
47	/// specification describes that.
48	/// See [`zvariant::Value::try_clone`] for more information.
49	fn clone(&self) -> Self {
50		let cloned_any_data = self.any_data.try_clone().unwrap_or_else(|err| {
51			panic!("Failure cloning 'any_data' field: {err:?}");
52		});
53
54		Self {
55			kind: self.kind.clone(),
56			detail1: self.detail1,
57			detail2: self.detail2,
58			any_data: cloned_any_data,
59			properties: QtProperties,
60		}
61	}
62}
63
64/// Unit struct placeholder for `EventBodyQtOwned.properties`
65///
66/// AT-SPI2 never reads or writes to `EventBodyQT.properties`.
67/// `QtProperties` has the appropriate implementations for `Serialize` and `Deserialize`
68/// to make it serialize as an a valid tuple and valid bytes deserialize as placeholder.
69#[derive(Debug, Copy, Clone, Deserialize, Type, Default, PartialEq)]
70#[zvariant(signature = "(so)")]
71pub(crate) struct QtProperties;
72
73impl Serialize for QtProperties {
74	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75	where
76		S: serde::ser::Serializer,
77	{
78		let mut tup = serializer.serialize_tuple(2)?;
79		tup.serialize_element(":0.0")?;
80		tup.serialize_element(&ObjectPath::from_static_str_unchecked("/"))?;
81		tup.end()
82	}
83}
84
85impl Default for EventBodyQtOwned {
86	fn default() -> Self {
87		Self {
88			kind: String::new(),
89			detail1: 0,
90			detail2: 0,
91			any_data: 0_u32.into(),
92			properties: QtProperties,
93		}
94	}
95}
96
97/// Unit struct placeholder for `EventBody.properties`
98///
99/// AT-SPI2 never reads or writes to `EventBody.properties`.
100/// `Properties` has the appropriate implementations for `Serialize` and `Deserialize`
101/// to make it serialize as an a valid dictionary and valid bytes deserialize as placeholder.
102#[derive(Debug, Copy, Clone, Type, Default, Deserialize, PartialEq)]
103#[zvariant(signature = "a{sv}")]
104pub(crate) struct Properties;
105
106impl Serialize for Properties {
107	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108	where
109		S: serde::ser::Serializer,
110	{
111		serializer.serialize_map(Some(0))?.end()
112	}
113}
114
115/// AT-SPI2 protocol native event body type.
116///
117/// All of the various signals in the AT-SPI2 protocol share this shape.
118/// Most toolkits and implementors emit this type, except for `Qt`, which has has its
119/// own type: [`EventBodyQtOwned`].
120///
121/// Signature `(siiva{sv})`,
122#[validate(signal: "PropertyChange")]
123#[derive(Debug, Serialize, Deserialize, PartialEq, Type)]
124pub struct EventBodyOwned {
125	/// kind variant, used for specifying an event triple "object:state-changed:focused",
126	/// the "focus" part of this event is what is contained within the kind.
127	#[serde(rename = "type")]
128	pub kind: String,
129
130	/// Generic detail1 value described by AT-SPI.
131	pub detail1: i32,
132
133	/// Generic detail2 value described by AT-SPI.
134	pub detail2: i32,
135
136	/// Generic `any_data` value described by AT-SPI.
137	/// This can be any type.
138	///
139	pub any_data: OwnedValue,
140
141	/// Not in use.
142	/// See: [`Properties`].
143	pub(crate) properties: Properties,
144}
145
146impl Default for EventBodyOwned {
147	fn default() -> Self {
148		Self {
149			kind: String::new(),
150			detail1: 0,
151			detail2: 0,
152			any_data: 0_u32.into(),
153			properties: Properties,
154		}
155	}
156}
157
158impl Clone for EventBodyOwned {
159	/// # Safety
160	///
161	/// This implementation of [`Clone`] *can panic!* although chances are slim.
162	///
163	/// If the following conditions are met:
164	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
165	/// 2. the maximum number of open files for the process is exceeded.
166	///
167	/// Then this function panic.
168	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
169	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
170	/// specification describes that.
171	/// See [`zvariant::Value::try_clone`] for more information.
172	fn clone(&self) -> Self {
173		let cloned_any_data = self.any_data.try_clone().unwrap_or_else(|err| {
174			panic!("Failure cloning 'any_data' field: {err:?}");
175		});
176
177		Self {
178			kind: self.kind.clone(),
179			detail1: self.detail1,
180			detail2: self.detail2,
181			any_data: cloned_any_data,
182			properties: Properties,
183		}
184	}
185}
186
187#[derive(Debug, Serialize, Deserialize, PartialEq, Type)]
188pub struct EventBodyBorrowed<'a> {
189	/// kind variant, used for specifying an event triple "object:state-changed:focused",
190	/// the "focus" part of this event is what is contained within the kind.
191	#[serde(rename = "type")]
192	#[serde(borrow)]
193	pub kind: &'a str,
194
195	/// Generic detail1 value described by AT-SPI.
196	pub detail1: i32,
197
198	/// Generic detail2 value described by AT-SPI.
199	pub detail2: i32,
200
201	/// Generic `any_data` value described by AT-SPI.
202	/// This can be any type.
203	#[serde(borrow)]
204	pub any_data: Value<'a>,
205
206	/// Not in use.
207	/// See: [`Properties`].
208	#[serde(skip_deserializing)]
209	pub(crate) properties: Properties,
210}
211
212impl Default for EventBodyBorrowed<'_> {
213	fn default() -> Self {
214		Self {
215			kind: "",
216			detail1: 0,
217			detail2: 0,
218			any_data: Value::new(0_u32),
219			properties: Properties,
220		}
221	}
222}
223
224impl EventBodyBorrowed<'_> {
225	/// Convert this borrowed event body to an owned event body.
226	///
227	/// # Errors
228	///
229	/// This will error if the following conditions are met:
230	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
231	/// 2. the maximum number of open files for the process is exceeded.
232	///
233	/// Chances are slim because none of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
234	/// See [`zvariant::Value::try_clone`] for more information.
235	pub fn to_fully_owned(&self) -> Result<EventBodyOwned, AtspiError> {
236		let owned_any_data = self.any_data.try_to_owned()?;
237
238		Ok(EventBodyOwned {
239			kind: self.kind.into(),
240			detail1: self.detail1,
241			detail2: self.detail2,
242			any_data: owned_any_data,
243			properties: Properties,
244		})
245	}
246}
247
248impl Clone for EventBodyBorrowed<'_> {
249	/// # Safety
250	///
251	/// This implementation of [`Clone`] *can panic!* although chances are slim.
252	///
253	/// If the following conditions are met:
254	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
255	/// 2. the maximum number of open files for the process is exceeded.
256	///
257	/// Then this function panic.
258	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
259	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
260	/// specification describes that.
261	/// See [`zvariant::Value::try_clone`] for more information.
262	fn clone(&self) -> Self {
263		let cloned_any_data = self.any_data.try_clone().unwrap_or_else(|err| {
264			panic!("Failure cloning 'any_data' field: {err:?}");
265		});
266
267		Self {
268			kind: self.kind,
269			detail1: self.detail1,
270			detail2: self.detail2,
271			any_data: cloned_any_data,
272			properties: Properties,
273		}
274	}
275}
276
277#[derive(Debug, Type, Deserialize, PartialEq)]
278pub struct EventBodyQtBorrowed<'m> {
279	/// kind variant, used for specifying an event triple "object:state-changed:focused",
280	/// the "focus" part of this event is what is contained within the kind.
281	#[serde(rename = "type")]
282	pub kind: &'m str,
283
284	/// Generic detail1 value described by AT-SPI.
285	pub detail1: i32,
286
287	/// Generic detail2 value described by AT-SPI.
288	pub detail2: i32,
289
290	/// Generic `any_data` value described by AT-SPI.
291	/// This can be any type.
292	#[serde(borrow)]
293	pub any_data: Value<'m>,
294
295	/// Not in use.
296	/// See: [`QtProperties`].
297	#[serde(skip_deserializing)]
298	pub(crate) properties: QtProperties,
299}
300
301impl Default for EventBodyQtBorrowed<'_> {
302	fn default() -> Self {
303		Self {
304			kind: "",
305			detail1: 0,
306			detail2: 0,
307			any_data: Value::new(0_u32),
308			properties: QtProperties,
309		}
310	}
311}
312
313impl Clone for EventBodyQtBorrowed<'_> {
314	/// # Safety
315	///
316	/// This implementation of [`Clone`] *can panic!* although chances are slim.
317	///
318	/// If the following conditions are met:
319	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
320	/// 2. the maximum number of open files for the process is exceeded.
321	///
322	/// Then this function panics.
323	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
324	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
325	/// specification describes that.
326	/// See [`zvariant::Value::try_clone`] for more information.
327	fn clone(&self) -> Self {
328		let cloned_any_data = self.any_data.try_clone().unwrap_or_else(|err| {
329			panic!("Failure cloning 'any_data' field: {err:?}");
330		});
331
332		Self {
333			kind: self.kind,
334			detail1: self.detail1,
335			detail2: self.detail2,
336			any_data: cloned_any_data,
337			properties: QtProperties,
338		}
339	}
340}
341
342impl EventBodyQtBorrowed<'_> {
343	/// Convert partially borrowed Qt event body to an owned event body.
344	///
345	/// # Errors
346	///
347	/// This will error if the following conditions are met:
348	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
349	/// 2. the maximum number of open files for the process is exceeded.
350	pub fn try_to_owned(&self) -> Result<EventBodyQtOwned, AtspiError> {
351		let any_data = self.any_data.try_to_owned()?;
352
353		Ok(EventBodyQtOwned {
354			kind: self.kind.to_owned(),
355			detail1: self.detail1,
356			detail2: self.detail2,
357			any_data,
358			properties: self.properties,
359		})
360	}
361}
362
363impl<'de> From<EventBodyQtBorrowed<'de>> for EventBodyBorrowed<'de> {
364	fn from(borrow: EventBodyQtBorrowed<'de>) -> Self {
365		let EventBodyQtBorrowed { kind, detail1, detail2, any_data, properties: _ } = borrow;
366
367		Self { kind, detail1, detail2, any_data, properties: Properties }
368	}
369}
370
371impl From<EventBodyQtOwned> for EventBodyOwned {
372	fn from(body: EventBodyQtOwned) -> Self {
373		Self {
374			kind: body.kind,
375			detail1: body.detail1,
376			detail2: body.detail2,
377			any_data: body.any_data,
378			properties: Properties,
379		}
380	}
381}
382
383/// Common event body that can be either owned or borrowed.
384///
385/// This is useful for APIs that can return either owned or borrowed event bodies.
386/// Having this type allows to be generic over the event body type.
387#[derive(Debug, Clone, PartialEq)]
388pub enum EventBody<'a> {
389	Owned(EventBodyOwned),
390	Borrowed(EventBodyBorrowed<'a>),
391}
392
393impl Default for EventBody<'_> {
394	fn default() -> Self {
395		Self::Borrowed(EventBodyBorrowed::default())
396	}
397}
398
399impl<'a> EventBody<'_> {
400	/// Non-consuming conversion to an owned event body.
401	///
402	/// Does cloning.
403	///
404	/// # Errors
405	/// The borrowed variant will error if the following conditions are met:  
406	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and  
407	/// 2. the maximum number of open files for the process is exceeded.
408	pub fn as_owned(&self) -> Result<EventBodyOwned, AtspiError> {
409		match self {
410			Self::Owned(owned) => Ok(owned.clone()),
411			Self::Borrowed(borrowed) => borrowed.to_fully_owned(),
412		}
413	}
414
415	/// Consuming conversion to an owned event body.
416	///
417	/// Does cloning.
418	///
419	/// # Errors
420	/// The borrowed variant will error if the following conditions are met:  
421	/// 1. the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and  
422	/// 2. the maximum number of open files for the process is exceeded.
423	pub fn into_owned(self) -> Result<EventBodyOwned, AtspiError> {
424		match self {
425			Self::Owned(owned) => Ok(owned),
426			Self::Borrowed(borrowed) => borrowed.to_fully_owned(),
427		}
428	}
429
430	/// The `kind` field as `&str`.
431	///
432	/// With both variants, this method returns a reference to the `kind` field.
433	#[must_use]
434	pub fn kind(&'a self) -> &'a str {
435		match self {
436			Self::Owned(owned) => owned.kind.as_str(),
437			Self::Borrowed(borrowed) => borrowed.kind,
438		}
439	}
440
441	/// Take or convert the `kind` field as `String`.
442	///
443	/// With the owned variant, this method takes the `kind` field and replaces it with an empty string.
444	/// With the borrowed variant, this method clones and allocates the `kind` field.
445	pub fn take_kind(&mut self) -> String {
446		match self {
447			Self::Owned(owned) => std::mem::take(&mut owned.kind),
448			Self::Borrowed(borrowed) => borrowed.kind.to_owned(),
449		}
450	}
451
452	/// The `detail1` field.
453	#[must_use]
454	pub fn detail1(&self) -> i32 {
455		match self {
456			Self::Owned(owned) => owned.detail1,
457			Self::Borrowed(borrowed) => borrowed.detail1,
458		}
459	}
460
461	/// The `detail2` field.
462	#[must_use]
463	pub fn detail2(&self) -> i32 {
464		match self {
465			Self::Owned(owned) => owned.detail2,
466			Self::Borrowed(borrowed) => borrowed.detail2,
467		}
468	}
469
470	/// The `any_data` field as `&Value`.
471	/// With both variants, this method returns a reference to the `any_data` field.
472	#[must_use]
473	pub fn any_data(&'a self) -> &'a Value<'a> {
474		match self {
475			Self::Owned(owned) => &owned.any_data,
476			Self::Borrowed(borrowed) => &borrowed.any_data,
477		}
478	}
479
480	/// Take or convert the `any_data` field as `OwnedValue`.
481	/// With the owned variant, this method takes the `any_data` field and replaces it with a default value.
482	/// As `Value` does not have a default value, we will replace with `0_u32`, a nbon-allocating value.
483	///
484	/// With the borrowed variant, this method clones and allocates the `any_data` field.
485	///
486	/// # Panics
487	/// This method will panic if the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
488	/// the maximum number of open files for the process is exceeded.
489	///
490	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
491	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
492	/// specification describes that.
493	pub fn take_any_data(&mut self) -> OwnedValue {
494		match self {
495			Self::Owned(owned) => std::mem::replace(&mut owned.any_data, 0_u32.into()),
496			Self::Borrowed(borrowed) => borrowed.any_data.try_to_owned().expect("cloning 'any_data' field should not fail because we do not expect it to hold an fd"),
497		}
498	}
499}
500
501impl Type for EventBody<'_> {
502	const SIGNATURE: &'static zvariant::Signature = EventBodyOwned::SIGNATURE;
503}
504
505impl<'de> Deserialize<'de> for EventBody<'de> {
506	fn deserialize<D>(deserializer: D) -> Result<EventBody<'de>, D::Error>
507	where
508		D: serde::de::Deserializer<'de>,
509	{
510		let borrowed = EventBodyBorrowed::deserialize(deserializer)?;
511		Ok(borrowed.into())
512	}
513}
514
515impl Serialize for EventBody<'_> {
516	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
517	where
518		S: serde::ser::Serializer,
519	{
520		match self {
521			EventBody::Owned(owned) => owned.serialize(serializer),
522			EventBody::Borrowed(borrowed) => borrowed.serialize(serializer),
523		}
524	}
525}
526
527impl From<EventBodyOwned> for EventBody<'_> {
528	fn from(owned: EventBodyOwned) -> Self {
529		EventBody::Owned(owned)
530	}
531}
532
533impl<'b> From<EventBodyBorrowed<'b>> for EventBody<'b> {
534	fn from(borrowed: EventBodyBorrowed<'b>) -> Self {
535		EventBody::Borrowed(borrowed)
536	}
537}
538
539impl From<EventBodyQtOwned> for EventBody<'_> {
540	fn from(qt_owned: EventBodyQtOwned) -> Self {
541		EventBody::Owned(qt_owned.into())
542	}
543}
544
545impl<'a> From<EventBodyQtBorrowed<'a>> for EventBody<'a> {
546	fn from(qt_borrowed: EventBodyQtBorrowed<'a>) -> Self {
547		EventBody::Borrowed(qt_borrowed.into())
548	}
549}
550
551impl From<EventBodyOwned> for EventBodyQtOwned {
552	fn from(owned: EventBodyOwned) -> Self {
553		Self {
554			kind: owned.kind,
555			detail1: owned.detail1,
556			detail2: owned.detail2,
557			any_data: owned.any_data,
558			properties: QtProperties,
559		}
560	}
561}
562
563impl<'a> From<EventBodyBorrowed<'a>> for EventBodyQtOwned {
564	fn from(borrowed: EventBodyBorrowed<'a>) -> Self {
565		Self {
566			kind: borrowed.kind.to_owned(),
567			detail1: borrowed.detail1,
568			detail2: borrowed.detail2,
569			any_data: borrowed
570				.any_data
571				.try_to_owned()
572				.expect("converting borrowed to owned should not fail"),
573			properties: QtProperties,
574		}
575	}
576}
577
578impl From<EventBody<'_>> for EventBodyQtOwned {
579	fn from(event: EventBody) -> Self {
580		match event {
581			EventBody::Owned(owned) => owned.into(),
582			EventBody::Borrowed(borrowed) => borrowed.into(),
583		}
584	}
585}
586
587impl PartialEq<EventBodyOwned> for EventBodyQtOwned {
588	fn eq(&self, other: &EventBodyOwned) -> bool {
589		self.kind == other.kind
590			&& self.detail1 == other.detail1
591			&& self.detail2 == other.detail2
592			&& self.any_data == other.any_data
593	}
594}
595
596impl PartialEq<EventBodyQtOwned> for EventBodyOwned {
597	fn eq(&self, other: &EventBodyQtOwned) -> bool {
598		self.kind == other.kind
599			&& self.detail1 == other.detail1
600			&& self.detail2 == other.detail2
601			&& self.any_data == other.any_data
602	}
603}
604
605impl PartialEq<EventBodyBorrowed<'_>> for EventBodyQtBorrowed<'_> {
606	fn eq(&self, other: &EventBodyBorrowed<'_>) -> bool {
607		self.kind == other.kind
608			&& self.detail1 == other.detail1
609			&& self.detail2 == other.detail2
610			&& self.any_data == other.any_data
611	}
612}
613
614impl PartialEq<EventBodyQtBorrowed<'_>> for EventBodyBorrowed<'_> {
615	fn eq(&self, other: &EventBodyQtBorrowed<'_>) -> bool {
616		self.kind == other.kind
617			&& self.detail1 == other.detail1
618			&& self.detail2 == other.detail2
619			&& self.any_data == other.any_data
620	}
621}
622
623#[cfg(test)]
624mod test {
625	use super::*;
626	use crate::ObjectRef;
627	use std::collections::HashMap;
628	use zvariant::{serialized::Context, LE};
629	use zvariant::{Array, ObjectPath, Value};
630
631	#[test]
632	fn owned_event_body_clone() {
633		let event = EventBodyOwned::default();
634		let cloned = event.clone();
635
636		assert_eq!(event, cloned);
637	}
638
639	#[test]
640	fn event_body_qt_clone() {
641		let event = EventBodyQtOwned::default();
642		let cloned = event.clone();
643
644		assert_eq!(event, cloned);
645	}
646
647	#[test]
648	fn event_body_borrowed_clone() {
649		let event = EventBodyBorrowed::default();
650		let cloned = event.clone();
651
652		assert_eq!(event, cloned);
653	}
654
655	#[test]
656	fn event_body_qt_borrowed_clone() {
657		let event = EventBodyQtBorrowed::default();
658		let cloned = event.clone();
659
660		assert_eq!(event, cloned);
661	}
662
663	#[test]
664	fn owned_event_body_default() {
665		let event = EventBodyOwned::default();
666
667		assert_eq!(event.kind, "");
668		assert_eq!(event.detail1, 0);
669		assert_eq!(event.detail2, 0);
670		assert_eq!(event.any_data, 0_u32.into());
671	}
672
673	#[test]
674	fn qt_event_body_default() {
675		let event = EventBodyQtOwned::default();
676
677		assert_eq!(event.kind, "");
678		assert_eq!(event.detail1, 0);
679		assert_eq!(event.detail2, 0);
680		assert_eq!(event.any_data, 0_u32.into());
681		assert_eq!(event.properties, QtProperties);
682	}
683
684	#[test]
685	fn event_body_borrowed_default() {
686		let event = EventBodyBorrowed::default();
687
688		assert_eq!(event.kind, "");
689		assert_eq!(event.detail1, 0);
690		assert_eq!(event.detail2, 0);
691		assert_eq!(event.any_data, Value::new(0_u32));
692	}
693
694	#[test]
695	fn qt_event_body_borrowed_default() {
696		let event = EventBodyQtBorrowed::default();
697
698		assert_eq!(event.kind, "");
699		assert_eq!(event.detail1, 0);
700		assert_eq!(event.detail2, 0);
701		assert_eq!(event.any_data, Value::new(0_u32));
702		assert_eq!(event.properties, QtProperties);
703	}
704
705	#[test]
706	fn event_body_default() {
707		let event = EventBody::default();
708
709		assert_eq!(event, EventBody::Borrowed(EventBodyBorrowed::default()));
710	}
711
712	#[test]
713	fn qt_to_owned() {
714		let qt = EventBodyQtOwned::default();
715		let owned: EventBodyOwned = EventBodyQtOwned::default().into();
716
717		assert_eq!(owned, qt);
718	}
719
720	#[test]
721	fn borrowed_to_qt() {
722		let borrowed: EventBodyBorrowed = EventBodyQtBorrowed::default().into();
723
724		assert_eq!(borrowed, EventBodyBorrowed::default());
725	}
726
727	#[test]
728	fn event_body_deserialize_as_owned() {
729		let event = EventBodyOwned::default();
730
731		let ctxt = Context::new_dbus(LE, 0);
732		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
733
734		let (deserialized, _) = bytes.deserialize::<EventBodyOwned>().unwrap();
735
736		assert_eq!(deserialized, event);
737	}
738
739	#[test]
740	fn owned_event_body_deserialize_as_borrowed() {
741		let event = EventBodyOwned::default();
742
743		let ctxt = Context::new_dbus(LE, 0);
744		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
745
746		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
747
748		assert_eq!(deserialized, EventBodyBorrowed::default());
749		assert_eq!(deserialized.kind, event.kind.as_str());
750		assert_eq!(deserialized.detail1, event.detail1);
751		assert_eq!(deserialized.detail2, event.detail2);
752		assert_eq!(deserialized.any_data, *event.any_data);
753	}
754
755	#[test]
756	fn qt_owned_event_body_deserialize_as_borrowed() {
757		let event = EventBodyQtOwned::default();
758
759		let ctxt = Context::new_dbus(LE, 0);
760		let bytes = zvariant::to_bytes::<EventBodyQtOwned>(ctxt, &event).unwrap();
761
762		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
763
764		assert_eq!(deserialized, EventBodyBorrowed::default());
765		assert_eq!(deserialized.kind, event.kind.as_str());
766		assert_eq!(deserialized.detail1, event.detail1);
767		assert_eq!(deserialized.detail2, event.detail2);
768		assert_eq!(deserialized.any_data, *event.any_data);
769	}
770
771	#[test]
772	fn event_body_default_deserialize_as_event_body() {
773		let event = EventBody::default();
774
775		let ctxt = Context::new_dbus(LE, 0);
776		let bytes = zvariant::to_bytes::<EventBody>(ctxt, &event).unwrap();
777
778		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
779
780		assert_eq!(deserialized, event);
781	}
782
783	#[test]
784	fn event_body_owned_default_deserialize_as_event_body() {
785		let event = EventBodyOwned::default();
786
787		let ctxt = Context::new_dbus(LE, 0);
788		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
789
790		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
791
792		assert_eq!(deserialized.kind(), event.kind.as_str());
793		assert_eq!(deserialized.detail1(), event.detail1);
794		assert_eq!(deserialized.detail2(), event.detail2);
795		assert_eq!(*deserialized.any_data(), *event.any_data);
796	}
797
798	#[test]
799	fn complex_body_deserialize_as_event_body() {
800		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
801		let boots = Value::from(boots);
802		let event = (
803			"object:state-changed:focused",
804			1,
805			2,
806			boots.clone(),
807			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
808		);
809
810		let ctxt = Context::new_dbus(LE, 0);
811		let bytes =
812			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
813				.unwrap();
814
815		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
816
817		assert_eq!(deserialized.kind(), "object:state-changed:focused");
818		assert_eq!(deserialized.detail1(), 1);
819		assert_eq!(deserialized.detail2(), 2);
820		assert_eq!(*deserialized.any_data(), boots);
821	}
822
823	#[test]
824	fn complex_body_deserialize_as_owned_event_body() {
825		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
826		let boots = Value::from(boots);
827		let event = (
828			"object:state-changed:focused",
829			1,
830			2,
831			boots.clone(),
832			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
833		);
834
835		let ctxt = Context::new_dbus(LE, 0);
836		let bytes =
837			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
838				.unwrap();
839
840		let (deserialized, _) = bytes.deserialize::<EventBodyOwned>().unwrap();
841
842		assert_eq!(deserialized.kind, "object:state-changed:focused");
843		assert_eq!(deserialized.detail1, 1);
844		assert_eq!(deserialized.detail2, 2);
845		assert_eq!(*deserialized.any_data, boots);
846	}
847
848	#[test]
849	fn complex_qt_body_as_bytes_deserialize_as_event_body() {
850		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
851		let boots = Value::from(boots);
852		let event = (
853			"and that is what they'll do",
854			1,
855			2,
856			boots.clone(),
857			(":0.0", ObjectPath::from_static_str_unchecked("/")),
858		);
859
860		let ctxt = Context::new_dbus(LE, 0);
861		let bytes = zvariant::to_bytes::<(&str, i32, i32, Value, (&str, ObjectPath))>(ctxt, &event)
862			.unwrap();
863
864		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
865
866		assert_eq!(deserialized.kind(), "and that is what they'll do");
867		assert_eq!(deserialized.detail1(), 1);
868		assert_eq!(deserialized.detail2(), 2);
869		assert_eq!(*deserialized.any_data(), boots);
870	}
871
872	#[test]
873	fn complex_qt_body_as_message_deserialize_as_event_body() {
874		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
875		let boots = Value::from(boots);
876		let event = (
877			"and that is what they'll do",
878			1,
879			2,
880			boots.clone(),
881			(":0.0", ObjectPath::from_static_str_unchecked("/")),
882		);
883
884		let msg = zbus::Message::signal("/", "org.a11y.atspi.Object", "StateChange")
885			.unwrap()
886			.build(&event)
887			.unwrap();
888
889		let body = msg.body();
890		let deserialized = body.deserialize_unchecked::<EventBody>().unwrap();
891
892		assert_eq!(deserialized.kind(), "and that is what they'll do");
893		assert_eq!(deserialized.detail1(), 1);
894		assert_eq!(deserialized.detail2(), 2);
895		assert_eq!(*deserialized.any_data(), boots);
896	}
897
898	#[test]
899	fn illegal_body_as_bytes_deserialize_as_event_body() {
900		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
901		let boots = Value::from(boots);
902		let event = (
903			"and that is what they'll do",
904			1,
905			2,
906			4_u32,
907			boots.clone(),
908			(":0.0", ObjectPath::from_static_str_unchecked("/")),
909		);
910
911		let ctxt = Context::new_dbus(LE, 0);
912		let bytes = zvariant::to_bytes::<(&str, i32, i32, u32, Value<'_>, (&str, ObjectPath<'_>))>(
913			ctxt, &event,
914		)
915		.unwrap();
916
917		assert!(bytes.deserialize::<EventBody>().is_err());
918	}
919
920	#[test]
921	fn complex_body_deserialize_as_borrowed_event_body() {
922		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
923		let boots = Value::from(boots);
924		let event = (
925			"object:state-changed:focused",
926			1,
927			2,
928			boots.clone(),
929			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
930		);
931
932		let ctxt = Context::new_dbus(LE, 0);
933		let bytes =
934			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
935				.unwrap();
936
937		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
938
939		assert_eq!(deserialized.kind, "object:state-changed:focused");
940		assert_eq!(deserialized.detail1, 1);
941		assert_eq!(deserialized.detail2, 2);
942		assert_eq!(deserialized.any_data, boots);
943	}
944
945	#[test]
946	fn deserialize_message_from_complex_message_data() {
947		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
948		let boots = Value::from(boots);
949		let body = (
950			"object:state-changed:focused",
951			1,
952			2,
953			boots.clone(),
954			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
955		);
956
957		let message = zbus::Message::signal("/", "org.a11y.atspi.Object", "StateChange")
958			.unwrap()
959			.build(&body)
960			.unwrap();
961
962		let msg_body = message.body();
963
964		let deserialized = msg_body.deserialize::<EventBodyOwned>().unwrap();
965
966		assert_eq!(deserialized.kind, "object:state-changed:focused");
967		assert_eq!(deserialized.detail1, 1);
968		assert_eq!(deserialized.detail2, 2);
969		assert_eq!(*deserialized.any_data, boots);
970	}
971
972	#[test]
973	fn simple_data_deserialization() {
974		let body = "hello";
975
976		let message = zbus::Message::signal("/bus/driver/zeenix", "org.Zbus", "TicketCheck")
977			.unwrap()
978			.build(&body)
979			.unwrap();
980
981		let msg_body = message.body();
982		let deserialized = msg_body.deserialize::<&str>().unwrap();
983
984		assert_eq!(deserialized, body);
985	}
986
987	#[test]
988	fn test_valid_hashmap_of_string_value_deserializes_as_properties() {
989		let val = Value::from(0_u32);
990		let key = "test";
991		let map = HashMap::from([(key, val)]);
992
993		let ctxt = Context::new_dbus(LE, 0);
994		let bytes = zvariant::to_bytes::<HashMap<&str, Value>>(ctxt, &map).unwrap();
995
996		let (properties, _) = bytes.deserialize::<Properties>().unwrap();
997
998		assert_eq!(properties, Properties);
999	}
1000
1001	#[test]
1002	fn test_object_ref_deserializes_as_qt_properties() {
1003		let object_ref = ObjectRef::default();
1004
1005		let ctxt = Context::new_dbus(LE, 0);
1006		let bytes = zvariant::to_bytes::<ObjectRef>(ctxt, &object_ref).unwrap();
1007
1008		let (qt_props, _) = bytes.deserialize::<QtProperties>().unwrap();
1009
1010		assert_eq!(qt_props, QtProperties);
1011	}
1012
1013	#[test]
1014	fn test_properties_serializes_as_valid_hashmap() {
1015		let properties = Properties;
1016		let ctxt = Context::new_dbus(LE, 0);
1017		let bytes = zvariant::to_bytes::<Properties>(ctxt, &properties).unwrap();
1018
1019		let (map, _) = bytes.deserialize::<HashMap<&str, Value>>().unwrap();
1020
1021		assert_eq!(map, HashMap::new());
1022	}
1023
1024	#[test]
1025	fn test_qt_properties_serializes_as_valid_string_objpath_tuple() {
1026		let qt_properties = QtProperties;
1027		let ctxt = Context::new_dbus(LE, 0);
1028		let bytes = zvariant::to_bytes::<QtProperties>(ctxt, &qt_properties).unwrap();
1029
1030		let (tuple, _) = bytes.deserialize::<(&str, ObjectPath)>().unwrap();
1031
1032		assert_eq!(tuple, (":0.0", ObjectPath::from_static_str_unchecked("/")));
1033	}
1034
1035	#[test]
1036	fn test_qt_properties_serializes_as_valid_object_ref() {
1037		let qt_properties = QtProperties;
1038		let ctxt = Context::new_dbus(LE, 0);
1039		let bytes = zvariant::to_bytes::<QtProperties>(ctxt, &qt_properties).unwrap();
1040
1041		let (objectref, _) = bytes.deserialize::<ObjectRef>().unwrap();
1042
1043		assert_eq!(objectref.name().unwrap().as_str(), ":0.0");
1044		assert_eq!(objectref.path(), &ObjectPath::from_static_str_unchecked("/"));
1045	}
1046
1047	#[cfg(test)]
1048	mod signatures {
1049		use crate::events::EventBodyQtOwned;
1050		use zvariant::{signature::Fields, Signature, Type};
1051
1052		#[test]
1053		fn test_event_body_signature_equals_borrowed_event_body_signature() {
1054			use super::*;
1055			use zvariant::Type;
1056
1057			let borrowed = EventBodyBorrowed::SIGNATURE;
1058			let owned = EventBodyOwned::SIGNATURE;
1059
1060			assert_eq!(borrowed, owned);
1061		}
1062
1063		// We have no definition of the Qt event body, so we can't compare the type
1064		// to a signature definition in XML.
1065		// That is why we keep a copy here.
1066		const QSPI_EVENT_SIGNATURE: &Signature = &Signature::static_structure(&[
1067			&Signature::Str,
1068			&Signature::I32,
1069			&Signature::I32,
1070			&Signature::Variant,
1071			&Signature::Structure(Fields::Static {
1072				fields: &[&Signature::Str, &Signature::ObjectPath],
1073			}),
1074		]);
1075
1076		#[test]
1077		fn check_event_body_qt_signature() {
1078			assert_eq!(<EventBodyQtOwned as Type>::SIGNATURE, QSPI_EVENT_SIGNATURE);
1079		}
1080	}
1081}