Skip to main content

logind_zbus_tokio/
lib.rs

1//! Reference <https://www.freedesktop.org/software/systemd/man/org.freedesktop.login1.html>
2
3use 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    /// The seat label
43    id: String,
44    /// DBUS path for this seat
45    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}