dbus_addr/transport/
unix.rs1use std::{borrow::Cow, ffi::OsStr};
2
3use super::{
4 percent::{decode_percents, decode_percents_os_str, decode_percents_str, EncData, EncOsStr},
5 DBusAddr, Error, KeyValFmt, Result, TransportImpl,
6};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct Unix<'a> {
13 kind: UnixAddrKind<'a>,
14}
15
16impl<'a> Unix<'a> {
17 pub fn kind(&self) -> &UnixAddrKind<'a> {
19 &self.kind
20 }
21
22 pub fn into_owned(self) -> Unix<'static> {
24 Unix {
25 kind: self.kind.into_owned(),
26 }
27 }
28}
29
30impl<'a> TransportImpl<'a> for Unix<'a> {
31 fn for_address(s: &'a DBusAddr<'a>) -> Result<Self> {
32 let mut kind = None;
33 let mut iter = s.key_val_iter();
34 for (k, v) in &mut iter {
35 match k {
36 "path" | "dir" | "tmpdir" => {
37 let v = v.ok_or_else(|| Error::MissingValue(k.into()))?;
38 let v = decode_percents_os_str(v)?;
39 kind = Some(match k {
40 "path" => UnixAddrKind::Path(v),
41 "dir" => UnixAddrKind::Dir(v),
42 "tmpdir" => UnixAddrKind::Tmpdir(v),
43 _ => panic!(),
45 });
46
47 break;
48 }
49 "abstract" => {
50 let v = v.ok_or_else(|| Error::MissingValue(k.into()))?;
51 let v = decode_percents(v)?;
52 kind = Some(UnixAddrKind::Abstract(v));
53
54 break;
55 }
56 "runtime" => {
57 let v = v.ok_or_else(|| Error::MissingValue(k.into()))?;
58 let v = decode_percents_str(v)?;
59 if v != "yes" {
60 return Err(Error::InvalidValue(k.into()));
61 }
62 kind = Some(UnixAddrKind::Runtime);
63
64 break;
65 }
66 _ => continue,
67 }
68 }
69 let Some(kind) = kind else {
70 return Err(Error::Other(
71 "invalid `unix:` address, missing required key".into(),
72 ));
73 };
74 for (k, _) in iter {
75 match k {
76 "path" | "dir" | "tmpdir" | "abstract" | "runtime" => {
77 return Err(Error::Other("invalid address, only one of `path` `dir` `tmpdir` `abstract` or `runtime` expected".into()));
78 }
79 _ => (),
80 }
81 }
82
83 Ok(Unix { kind })
84 }
85
86 fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> {
87 self.kind().fmt_key_val(kv)
88 }
89}
90
91#[derive(Clone, Debug, PartialEq, Eq)]
93#[non_exhaustive]
94pub enum UnixAddrKind<'a> {
95 Path(Cow<'a, OsStr>),
97 Dir(Cow<'a, OsStr>),
100 Tmpdir(Cow<'a, OsStr>),
104 Abstract(Cow<'a, [u8]>),
107 Runtime,
109}
110
111impl UnixAddrKind<'_> {
112 fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> {
113 match self {
114 UnixAddrKind::Path(p) => kv.add("path", Some(EncOsStr(p))),
115 UnixAddrKind::Dir(p) => kv.add("dir", Some(EncOsStr(p))),
116 UnixAddrKind::Tmpdir(p) => kv.add("tmpdir", Some(EncOsStr(p))),
117 UnixAddrKind::Abstract(p) => kv.add("abstract", Some(EncData(p))),
118 UnixAddrKind::Runtime => kv.add("runtime", Some("yes")),
119 }
120 }
121
122 fn into_owned(self) -> UnixAddrKind<'static> {
123 match self {
124 UnixAddrKind::Path(cow) => UnixAddrKind::Path(cow.into_owned().into()),
125 UnixAddrKind::Dir(cow) => UnixAddrKind::Dir(cow.into_owned().into()),
126 UnixAddrKind::Tmpdir(cow) => UnixAddrKind::Tmpdir(cow.into_owned().into()),
127 UnixAddrKind::Abstract(cow) => UnixAddrKind::Abstract(cow.into_owned().into()),
128 UnixAddrKind::Runtime => UnixAddrKind::Runtime,
129 }
130 }
131}