dbus_addr/
address.rs

1use std::borrow::Cow;
2
3use super::{
4    decode_percents, decode_percents_str, transport, transport::TransportImpl, Error, Guid,
5    KeyValIter, Result,
6};
7
8/// A parsed bus address.
9///
10/// The fields of this structure are references to the source. Using an [`crate::OwnedDBusAddr`] may
11/// be more convenient or if your context requires 'static lifetime.
12///
13/// Example:
14/// ```
15/// use dbus_addr::DBusAddr;
16///
17/// let _: DBusAddr = "unix:path=/tmp/dbus.sock".try_into().unwrap();
18/// ```
19#[derive(Debug, PartialEq, Eq, Clone)]
20pub struct DBusAddr<'a> {
21    pub(super) addr: Cow<'a, str>,
22}
23
24impl<'a> DBusAddr<'a> {
25    /// The connection GUID if any.
26    pub fn guid(&self) -> Result<Option<Guid>> {
27        if let Some(guid) = self.get_string("guid") {
28            Ok(Some(guid?.as_ref().try_into()?))
29        } else {
30            Ok(None)
31        }
32    }
33
34    /// Transport connection details
35    pub fn transport(&self) -> Result<transport::Transport<'_>> {
36        transport::Transport::for_address(self)
37    }
38
39    /// This address as a string slice.
40    pub fn as_str(&self) -> &str {
41        match &self.addr {
42            Cow::Borrowed(a) => a,
43            Cow::Owned(a) => a.as_str(),
44        }
45    }
46
47    pub(super) fn key_val_iter(&'a self) -> KeyValIter<'a> {
48        let mut split = self.addr.splitn(2, ':');
49        // skip transport:..
50        split.next();
51        let kv = split.next().unwrap_or("");
52        KeyValIter::new(kv)
53    }
54
55    fn new<A: Into<Cow<'a, str>>>(addr: A) -> Result<Self> {
56        let addr = addr.into();
57        let addr = Self { addr };
58
59        addr.validate()?;
60
61        Ok(addr)
62    }
63
64    fn validate(&self) -> Result<()> {
65        self.transport()?;
66        for (k, v) in self.key_val_iter() {
67            match (k, v) {
68                ("guid", Some(v)) => {
69                    Guid::try_from(decode_percents_str(v)?.as_ref())?;
70                }
71                (_, Some(v)) => {
72                    decode_percents(v)?;
73                }
74                _ => {}
75            }
76        }
77
78        Ok(())
79    }
80
81    // the last key=val wins
82    fn get_string(&'a self, key: &str) -> Option<Result<Cow<'a, str>>> {
83        let mut val = None;
84        for (k, v) in self.key_val_iter() {
85            if key == k {
86                val = v;
87            }
88        }
89        val.map(decode_percents_str)
90    }
91}
92
93impl<'a> TryFrom<String> for DBusAddr<'a> {
94    type Error = Error;
95
96    fn try_from(addr: String) -> Result<Self> {
97        Self::new(addr)
98    }
99}
100
101impl<'a> TryFrom<&'a str> for DBusAddr<'a> {
102    type Error = Error;
103
104    fn try_from(addr: &'a str) -> Result<Self> {
105        Self::new(addr)
106    }
107}
108
109/// A trait for objects which can be converted or resolved to one or more [`DBusAddr`] values.
110pub trait ToDBusAddrs<'a> {
111    type Iter: Iterator<Item = Result<DBusAddr<'a>>>;
112
113    fn to_dbus_addrs(&'a self) -> Self::Iter;
114}
115
116impl<'a> ToDBusAddrs<'a> for DBusAddr<'a> {
117    type Iter = std::iter::Once<Result<DBusAddr<'a>>>;
118
119    /// Get an iterator over the D-Bus addresses.
120    fn to_dbus_addrs(&'a self) -> Self::Iter {
121        std::iter::once(Ok(self.clone()))
122    }
123}
124
125impl<'a> ToDBusAddrs<'a> for str {
126    type Iter = std::iter::Once<Result<DBusAddr<'a>>>;
127
128    fn to_dbus_addrs(&'a self) -> Self::Iter {
129        std::iter::once(self.try_into())
130    }
131}
132
133impl<'a> ToDBusAddrs<'a> for String {
134    type Iter = std::iter::Once<Result<DBusAddr<'a>>>;
135
136    fn to_dbus_addrs(&'a self) -> Self::Iter {
137        std::iter::once(self.as_str().try_into())
138    }
139}
140
141impl<'a> ToDBusAddrs<'a> for Vec<Result<DBusAddr<'_>>> {
142    type Iter = std::iter::Cloned<std::slice::Iter<'a, Result<DBusAddr<'a>>>>;
143
144    fn to_dbus_addrs(&'a self) -> Self::Iter {
145        self.iter().cloned()
146    }
147}