atspi_common/events/
event_body.rs

1use crate::AtspiError;
2use serde::{
3	ser::{SerializeMap, SerializeStruct},
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 `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 structure = serializer.serialize_struct("ObjectRef", 2)?;
79		structure.serialize_field("name", ":0.0")?;
80		structure.serialize_field("path", &ObjectPath::from_static_str_unchecked("/"))?;
81		structure.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	#[must_use]
453	pub fn detail1(&self) -> i32 {
454		match self {
455			Self::Owned(owned) => owned.detail1,
456			Self::Borrowed(borrowed) => borrowed.detail1,
457		}
458	}
459
460	#[must_use]
461	pub fn detail2(&self) -> i32 {
462		match self {
463			Self::Owned(owned) => owned.detail2,
464			Self::Borrowed(borrowed) => borrowed.detail2,
465		}
466	}
467
468	/// The `any_data` field as `&Value`.
469	/// With both variants, this method returns a reference to the `any_data` field.
470	#[must_use]
471	pub fn any_data(&'a self) -> &'a Value<'a> {
472		match self {
473			Self::Owned(owned) => &owned.any_data,
474			Self::Borrowed(borrowed) => &borrowed.any_data,
475		}
476	}
477
478	/// Take or convert the `any_data` field as `OwnedValue`.
479	/// With the owned variant, this method takes the `any_data` field and replaces it with a default value.
480	/// As `Value` does not have a default value, we will replace with `0_u32`, a nbon-allocating value.
481	///
482	/// With the borrowed variant, this method clones and allocates the `any_data` field.
483	///
484	/// # Panics
485	/// This method will panic if the `any_data` field contains an [`std::os::fd::OwnedFd`] type, and
486	/// the maximum number of open files for the process is exceeded.
487	///
488	/// None of the types in [`crate::events`] use [`std::os::fd::OwnedFd`].
489	/// Events on the AT-SPI bus *could, theoretically* send a file descriptor, but nothing in the current
490	/// specification describes that.
491	pub fn take_any_data(&mut self) -> OwnedValue {
492		match self {
493			Self::Owned(owned) => std::mem::replace(&mut owned.any_data, 0_u32.into()),
494			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"),
495		}
496	}
497}
498
499impl Type for EventBody<'_> {
500	const SIGNATURE: &'static zvariant::Signature = EventBodyOwned::SIGNATURE;
501}
502
503impl<'de> Deserialize<'de> for EventBody<'de> {
504	fn deserialize<D>(deserializer: D) -> Result<EventBody<'de>, D::Error>
505	where
506		D: serde::de::Deserializer<'de>,
507	{
508		let borrowed = EventBodyBorrowed::deserialize(deserializer)?;
509		Ok(borrowed.into())
510	}
511}
512
513impl Serialize for EventBody<'_> {
514	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
515	where
516		S: serde::ser::Serializer,
517	{
518		match self {
519			EventBody::Owned(owned) => owned.serialize(serializer),
520			EventBody::Borrowed(borrowed) => borrowed.serialize(serializer),
521		}
522	}
523}
524
525impl From<EventBodyOwned> for EventBody<'_> {
526	fn from(owned: EventBodyOwned) -> Self {
527		EventBody::Owned(owned)
528	}
529}
530
531impl<'b> From<EventBodyBorrowed<'b>> for EventBody<'b> {
532	fn from(borrowed: EventBodyBorrowed<'b>) -> Self {
533		EventBody::Borrowed(borrowed)
534	}
535}
536
537impl From<EventBodyQtOwned> for EventBody<'_> {
538	fn from(qt_owned: EventBodyQtOwned) -> Self {
539		EventBody::Owned(qt_owned.into())
540	}
541}
542
543impl<'a> From<EventBodyQtBorrowed<'a>> for EventBody<'a> {
544	fn from(qt_borrowed: EventBodyQtBorrowed<'a>) -> Self {
545		EventBody::Borrowed(qt_borrowed.into())
546	}
547}
548
549impl From<EventBodyOwned> for EventBodyQtOwned {
550	fn from(owned: EventBodyOwned) -> Self {
551		Self {
552			kind: owned.kind,
553			detail1: owned.detail1,
554			detail2: owned.detail2,
555			any_data: owned.any_data,
556			properties: QtProperties,
557		}
558	}
559}
560
561impl<'a> From<EventBodyBorrowed<'a>> for EventBodyQtOwned {
562	fn from(borrowed: EventBodyBorrowed<'a>) -> Self {
563		Self {
564			kind: borrowed.kind.to_owned(),
565			detail1: borrowed.detail1,
566			detail2: borrowed.detail2,
567			any_data: borrowed
568				.any_data
569				.try_to_owned()
570				.expect("converting borrowed to owned should not fail"),
571			properties: QtProperties,
572		}
573	}
574}
575
576impl From<EventBody<'_>> for EventBodyQtOwned {
577	fn from(event: EventBody) -> Self {
578		match event {
579			EventBody::Owned(owned) => owned.into(),
580			EventBody::Borrowed(borrowed) => borrowed.into(),
581		}
582	}
583}
584
585impl PartialEq<EventBodyOwned> for EventBodyQtOwned {
586	fn eq(&self, other: &EventBodyOwned) -> bool {
587		self.kind == other.kind
588			&& self.detail1 == other.detail1
589			&& self.detail2 == other.detail2
590			&& self.any_data == other.any_data
591	}
592}
593
594impl PartialEq<EventBodyQtOwned> for EventBodyOwned {
595	fn eq(&self, other: &EventBodyQtOwned) -> bool {
596		self.kind == other.kind
597			&& self.detail1 == other.detail1
598			&& self.detail2 == other.detail2
599			&& self.any_data == other.any_data
600	}
601}
602
603impl PartialEq<EventBodyBorrowed<'_>> for EventBodyQtBorrowed<'_> {
604	fn eq(&self, other: &EventBodyBorrowed<'_>) -> bool {
605		self.kind == other.kind
606			&& self.detail1 == other.detail1
607			&& self.detail2 == other.detail2
608			&& self.any_data == other.any_data
609	}
610}
611
612impl PartialEq<EventBodyQtBorrowed<'_>> for EventBodyBorrowed<'_> {
613	fn eq(&self, other: &EventBodyQtBorrowed<'_>) -> bool {
614		self.kind == other.kind
615			&& self.detail1 == other.detail1
616			&& self.detail2 == other.detail2
617			&& self.any_data == other.any_data
618	}
619}
620
621#[cfg(test)]
622mod test {
623	use super::*;
624	use crate::ObjectRef;
625	use std::collections::HashMap;
626	use zvariant::{serialized::Context, LE};
627	use zvariant::{Array, ObjectPath, Value};
628
629	#[test]
630	fn owned_event_body_clone() {
631		let event = EventBodyOwned::default();
632		let cloned = event.clone();
633
634		assert_eq!(event, cloned);
635	}
636
637	#[test]
638	fn event_body_qt_clone() {
639		let event = EventBodyQtOwned::default();
640		let cloned = event.clone();
641
642		assert_eq!(event, cloned);
643	}
644
645	#[test]
646	fn event_body_borrowed_clone() {
647		let event = EventBodyBorrowed::default();
648		let cloned = event.clone();
649
650		assert_eq!(event, cloned);
651	}
652
653	#[test]
654	fn event_body_qt_borrowed_clone() {
655		let event = EventBodyQtBorrowed::default();
656		let cloned = event.clone();
657
658		assert_eq!(event, cloned);
659	}
660
661	#[test]
662	fn owned_event_body_default() {
663		let event = EventBodyOwned::default();
664
665		assert_eq!(event.kind, "");
666		assert_eq!(event.detail1, 0);
667		assert_eq!(event.detail2, 0);
668		assert_eq!(event.any_data, 0_u32.into());
669	}
670
671	#[test]
672	fn qt_event_body_default() {
673		let event = EventBodyQtOwned::default();
674
675		assert_eq!(event.kind, "");
676		assert_eq!(event.detail1, 0);
677		assert_eq!(event.detail2, 0);
678		assert_eq!(event.any_data, 0_u32.into());
679		assert_eq!(event.properties, QtProperties);
680	}
681
682	#[test]
683	fn event_body_borrowed_default() {
684		let event = EventBodyBorrowed::default();
685
686		assert_eq!(event.kind, "");
687		assert_eq!(event.detail1, 0);
688		assert_eq!(event.detail2, 0);
689		assert_eq!(event.any_data, Value::new(0_u32));
690	}
691
692	#[test]
693	fn qt_event_body_borrowed_default() {
694		let event = EventBodyQtBorrowed::default();
695
696		assert_eq!(event.kind, "");
697		assert_eq!(event.detail1, 0);
698		assert_eq!(event.detail2, 0);
699		assert_eq!(event.any_data, Value::new(0_u32));
700		assert_eq!(event.properties, QtProperties);
701	}
702
703	#[test]
704	fn event_body_default() {
705		let event = EventBody::default();
706
707		assert_eq!(event, EventBody::Borrowed(EventBodyBorrowed::default()));
708	}
709
710	#[test]
711	fn qt_to_owned() {
712		let qt = EventBodyQtOwned::default();
713		let owned: EventBodyOwned = EventBodyQtOwned::default().into();
714
715		assert_eq!(owned, qt);
716	}
717
718	#[test]
719	fn borrowed_to_qt() {
720		let borrowed: EventBodyBorrowed = EventBodyQtBorrowed::default().into();
721
722		assert_eq!(borrowed, EventBodyBorrowed::default());
723	}
724
725	#[test]
726	fn event_body_deserialize_as_owned() {
727		let event = EventBodyOwned::default();
728
729		let ctxt = Context::new_dbus(LE, 0);
730		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
731
732		let (deserialized, _) = bytes.deserialize::<EventBodyOwned>().unwrap();
733
734		assert_eq!(deserialized, event);
735	}
736
737	#[test]
738	fn owned_event_body_deserialize_as_borrowed() {
739		let event = EventBodyOwned::default();
740
741		let ctxt = Context::new_dbus(LE, 0);
742		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
743
744		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
745
746		assert_eq!(deserialized, EventBodyBorrowed::default());
747		assert_eq!(deserialized.kind, event.kind.as_str());
748		assert_eq!(deserialized.detail1, event.detail1);
749		assert_eq!(deserialized.detail2, event.detail2);
750		assert_eq!(deserialized.any_data, *event.any_data);
751	}
752
753	#[test]
754	fn qt_owned_event_body_deserialize_as_borrowed() {
755		let event = EventBodyQtOwned::default();
756
757		let ctxt = Context::new_dbus(LE, 0);
758		let bytes = zvariant::to_bytes::<EventBodyQtOwned>(ctxt, &event).unwrap();
759
760		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
761
762		assert_eq!(deserialized, EventBodyBorrowed::default());
763		assert_eq!(deserialized.kind, event.kind.as_str());
764		assert_eq!(deserialized.detail1, event.detail1);
765		assert_eq!(deserialized.detail2, event.detail2);
766		assert_eq!(deserialized.any_data, *event.any_data);
767	}
768
769	#[test]
770	fn event_body_default_deserialize_as_event_body() {
771		let event = EventBody::default();
772
773		let ctxt = Context::new_dbus(LE, 0);
774		let bytes = zvariant::to_bytes::<EventBody>(ctxt, &event).unwrap();
775
776		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
777
778		assert_eq!(deserialized, event);
779	}
780
781	#[test]
782	fn event_body_owned_default_deserialize_as_event_body() {
783		let event = EventBodyOwned::default();
784
785		let ctxt = Context::new_dbus(LE, 0);
786		let bytes = zvariant::to_bytes::<EventBodyOwned>(ctxt, &event).unwrap();
787
788		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
789
790		assert_eq!(deserialized.kind(), event.kind.as_str());
791		assert_eq!(deserialized.detail1(), event.detail1);
792		assert_eq!(deserialized.detail2(), event.detail2);
793		assert_eq!(*deserialized.any_data(), *event.any_data);
794	}
795
796	#[test]
797	fn complex_body_deserialize_as_event_body() {
798		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
799		let boots = Value::from(boots);
800		let event = (
801			"object:state-changed:focused",
802			1,
803			2,
804			boots.clone(),
805			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
806		);
807
808		let ctxt = Context::new_dbus(LE, 0);
809		let bytes =
810			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
811				.unwrap();
812
813		let (deserialized, _) = bytes.deserialize::<EventBody>().unwrap();
814
815		assert_eq!(deserialized.kind(), "object:state-changed:focused");
816		assert_eq!(deserialized.detail1(), 1);
817		assert_eq!(deserialized.detail2(), 2);
818		assert_eq!(*deserialized.any_data(), boots);
819	}
820
821	#[test]
822	fn complex_body_deserialize_as_owned_event_body() {
823		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
824		let boots = Value::from(boots);
825		let event = (
826			"object:state-changed:focused",
827			1,
828			2,
829			boots.clone(),
830			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
831		);
832
833		let ctxt = Context::new_dbus(LE, 0);
834		let bytes =
835			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
836				.unwrap();
837
838		let (deserialized, _) = bytes.deserialize::<EventBodyOwned>().unwrap();
839
840		assert_eq!(deserialized.kind, "object:state-changed:focused");
841		assert_eq!(deserialized.detail1, 1);
842		assert_eq!(deserialized.detail2, 2);
843		assert_eq!(*deserialized.any_data, boots);
844	}
845
846	#[test]
847	fn complex_body_deserialize_as_borrowed_event_body() {
848		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
849		let boots = Value::from(boots);
850		let event = (
851			"object:state-changed:focused",
852			1,
853			2,
854			boots.clone(),
855			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
856		);
857
858		let ctxt = Context::new_dbus(LE, 0);
859		let bytes =
860			zvariant::to_bytes::<(&str, i32, i32, Value, HashMap<&str, Value>)>(ctxt, &event)
861				.unwrap();
862
863		let (deserialized, _) = bytes.deserialize::<EventBodyBorrowed>().unwrap();
864
865		assert_eq!(deserialized.kind, "object:state-changed:focused");
866		assert_eq!(deserialized.detail1, 1);
867		assert_eq!(deserialized.detail2, 2);
868		assert_eq!(deserialized.any_data, boots);
869	}
870
871	#[test]
872	fn deserialize_message_from_complex_message_data() {
873		let boots = Array::from(vec!["these", "boots", "are", "made", "for", "walking"]);
874		let boots = Value::from(boots);
875		let body = (
876			"object:state-changed:focused",
877			1,
878			2,
879			boots.clone(),
880			HashMap::from([("key", Value::from(55_u32)), ("key2", Value::from(56_u32))]),
881		);
882
883		let message = zbus::Message::signal("/", "org.a11y.atspi.Object", "StateChange")
884			.unwrap()
885			.build(&body)
886			.unwrap();
887
888		let msg_body = message.body();
889
890		let deserialized = msg_body.deserialize::<EventBodyOwned>().unwrap();
891
892		assert_eq!(deserialized.kind, "object:state-changed:focused");
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 simple_data_deserialization() {
900		let body = "hello";
901
902		let message = zbus::Message::signal("/bus/driver/zeenix", "org.Zbus", "TicketCheck")
903			.unwrap()
904			.build(&body)
905			.unwrap();
906
907		let msg_body = message.body();
908		let deserialized = msg_body.deserialize::<&str>().unwrap();
909
910		assert_eq!(deserialized, body);
911	}
912
913	#[test]
914	fn test_valid_hashmap_of_string_value_deserializes_as_properties() {
915		let val = Value::from(0_u32);
916		let key = "test";
917		let map = HashMap::from([(key, val)]);
918
919		let ctxt = Context::new_dbus(LE, 0);
920		let bytes = zvariant::to_bytes::<HashMap<&str, Value>>(ctxt, &map).unwrap();
921
922		let (properties, _) = bytes.deserialize::<Properties>().unwrap();
923
924		assert_eq!(properties, Properties);
925	}
926
927	#[test]
928	fn test_object_ref_deserializes_as_qt_properties() {
929		let object_ref = ObjectRef::default();
930
931		let ctxt = Context::new_dbus(LE, 0);
932		let bytes = zvariant::to_bytes::<ObjectRef>(ctxt, &object_ref).unwrap();
933
934		let (qt_props, _) = bytes.deserialize::<QtProperties>().unwrap();
935
936		assert_eq!(qt_props, QtProperties);
937	}
938
939	#[test]
940	fn test_properties_serializes_as_valid_hashmap() {
941		let properties = Properties;
942		let ctxt = Context::new_dbus(LE, 0);
943		let bytes = zvariant::to_bytes::<Properties>(ctxt, &properties).unwrap();
944
945		let (map, _) = bytes.deserialize::<HashMap<&str, Value>>().unwrap();
946
947		assert_eq!(map, HashMap::new());
948	}
949
950	#[test]
951	fn test_qt_properties_serializes_as_valid_string_objpath_tuple() {
952		let qt_properties = QtProperties;
953		let ctxt = Context::new_dbus(LE, 0);
954		let bytes = zvariant::to_bytes::<QtProperties>(ctxt, &qt_properties).unwrap();
955
956		let (tuple, _) = bytes.deserialize::<(&str, ObjectPath)>().unwrap();
957
958		assert_eq!(tuple, (":0.0", ObjectPath::from_static_str_unchecked("/")));
959	}
960
961	#[test]
962	fn test_qt_properties_serializes_as_valid_object_ref() {
963		let qt_properties = QtProperties;
964		let ctxt = Context::new_dbus(LE, 0);
965		let bytes = zvariant::to_bytes::<QtProperties>(ctxt, &qt_properties).unwrap();
966
967		let (objectref, _) = bytes.deserialize::<ObjectRef>().unwrap();
968
969		assert_eq!(objectref.name, ":0.0");
970		assert_eq!(objectref.path, ObjectPath::from_static_str_unchecked("/").into());
971	}
972
973	#[cfg(test)]
974	mod signatures {
975		#[test]
976		fn test_event_body_signature_equals_borrowed_event_body_signature() {
977			use super::*;
978			use zvariant::Type;
979
980			let borrowed = EventBodyBorrowed::SIGNATURE;
981			let owned = EventBodyOwned::SIGNATURE;
982
983			assert_eq!(borrowed, owned);
984		}
985	}
986}