1use std::borrow::Cow;
2
3use super::{
4 decode_percents, decode_percents_str, transport, transport::TransportImpl, Error, Guid,
5 KeyValIter, Result,
6};
7
8#[derive(Debug, PartialEq, Eq, Clone)]
20pub struct DBusAddr<'a> {
21 pub(super) addr: Cow<'a, str>,
22}
23
24impl<'a> DBusAddr<'a> {
25 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 pub fn transport(&self) -> Result<transport::Transport<'_>> {
36 transport::Transport::for_address(self)
37 }
38
39 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 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 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
109pub 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 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}