1use std::{
4 ops::{Deref, DerefMut},
5 time::Duration,
6};
7
8use serde::{Deserialize, Serialize};
9use zbus::zvariant::{OwnedObjectPath, OwnedValue, Structure, Type};
10pub mod manager;
11pub mod seat;
12pub mod session;
13pub mod user;
14
15pub struct TimeStamp(Duration);
16
17impl Deref for TimeStamp {
18 type Target = Duration;
19
20 fn deref(&self) -> &Self::Target {
21 &self.0
22 }
23}
24
25impl DerefMut for TimeStamp {
26 fn deref_mut(&mut self) -> &mut Self::Target {
27 &mut self.0
28 }
29}
30
31impl TryFrom<OwnedValue> for TimeStamp {
32 type Error = zbus::Error;
33
34 fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
35 let value = <u64>::try_from(value)?;
36 Ok(Self(Duration::from_micros(value)))
37 }
38}
39
40#[derive(Debug, PartialEq, Eq, Clone, Type, Serialize, Deserialize)]
41pub struct SomePath {
42 id: String,
44 path: OwnedObjectPath,
46}
47
48impl SomePath {
49 pub fn id(&self) -> &str {
50 &self.id
51 }
52
53 pub fn path(&self) -> &OwnedObjectPath {
54 &self.path
55 }
56}
57
58impl TryFrom<OwnedValue> for SomePath {
59 type Error = zbus::Error;
60
61 fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
62 let value = <Structure<'_>>::try_from(value)?;
63 Ok(Self {
64 id: <String>::try_from(value.fields()[0].try_clone()?)?,
65 path: <OwnedObjectPath>::try_from(value.fields()[1].try_clone()?)?,
66 })
67 }
68}
69
70#[macro_export]
71macro_rules! enum_impl_serde_str {
72 ($type_name:ident) => {
73 impl Serialize for $type_name {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::Serializer,
77 {
78 serializer.serialize_str(self.into())
79 }
80 }
81
82 impl<'de> Deserialize<'de> for $type_name {
83 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
84 where
85 D: serde::Deserializer<'de>,
86 {
87 let s = String::deserialize(deserializer)?;
88 $type_name::from_str(s.as_str()).map_err(serde::de::Error::custom)
89 }
90 }
91 };
92}
93
94#[macro_export]
95macro_rules! impl_try_from_owned_as_str {
96 ($type_name:ident) => {
97 impl TryFrom<OwnedValue> for $type_name {
98 type Error = zbus::Error;
99
100 fn try_from(value: OwnedValue) -> Result<Self, Self::Error> {
101 let value = <String>::try_from(value)?;
102 return Ok($type_name::from_str(value.as_str())?);
103 }
104 }
105 };
106}
107
108#[macro_export]
109macro_rules! enum_impl_str_conv {
110 ($type_name:ident, { $($label:tt : $variant:tt,)* }) => {
111 impl FromStr for $type_name {
112 type Err = fdo::Error;
113
114 fn from_str(m: &str) -> Result<Self, Self::Err> {
115 let res = match m {
116 $($label => $type_name::$variant,)+
117 _ => return Err(fdo::Error::IOError(format!("{} is an invalid variant", m))),
118 };
119 Ok(res)
120 }
121 }
122
123 impl From<$type_name> for &str {
124 fn from(m: $type_name) -> Self {
125 match m {
126 $($type_name::$variant => $label,)+
127 }
128 }
129 }
130
131 impl From<&$type_name> for &str {
132 fn from(s: &$type_name) -> Self {
133 <&str>::from(*s)
134 }
135 }
136}}
137
138#[cfg(not(feature = "tokio"))]
139#[cfg(test)]
140mod tests {
141 use crate::{manager::ManagerProxyBlocking, session::SessionProxyBlocking};
142
143 #[test]
144 fn basic_test() {
145 let connection = zbus::blocking::Connection::system().unwrap();
146 let manager = ManagerProxyBlocking::new(&connection).unwrap();
147 let sessions = manager.list_sessions().unwrap();
148 let session_proxy = SessionProxyBlocking::builder(&connection)
149 .path(sessions[0].path())
150 .unwrap()
151 .build()
152 .unwrap();
153
154 assert!(session_proxy.seat().is_ok());
155 }
156}