dbus_server_address_parser/decode/
unix.rs1use super::{
2 unescape::{unescape, UnescapeError},
3 GuidError,
4};
5use crate::{Unix, UnixType};
6use std::convert::TryFrom;
7use thiserror::Error;
8
9use super::guid::decode_guid;
10
11#[derive(Error, Debug, Clone)]
12pub enum UnixError {
13 #[error("Could not unescape: {0}")]
14 UnescapeError(#[from] UnescapeError),
15 #[error("GUID error: {0}")]
16 GuidError(#[from] GuidError),
17 #[error("Unknown key")]
18 UnknownKey,
19 #[error("Unknown runtime")]
20 UnknownRuntime,
21 #[error("Type is duplicate")]
22 TypeDuplicate,
23 #[error("Type is missing")]
24 TypeMissing,
25}
26
27impl Unix {
28 fn decode_type(type_str: &str, r#type: &mut Option<UnixType>) -> Result<(), UnixError> {
29 if r#type.is_none() {
30 *r#type = Some(UnixType::try_from(type_str)?);
31 Ok(())
32 } else {
33 Err(UnixError::TypeDuplicate)
34 }
35 }
36}
37
38impl TryFrom<&str> for Unix {
39 type Error = UnixError;
40
41 fn try_from(server_address: &str) -> Result<Self, Self::Error> {
42 let mut r#type = None;
43 let mut guid = None;
44
45 for key_value in server_address.split(',') {
46 if let Some(guid_str) = key_value.strip_prefix("guid=") {
47 decode_guid(guid_str, &mut guid)?;
48 } else {
49 Unix::decode_type(key_value, &mut r#type)?;
50 }
51 }
52
53 if let Some(r#type) = r#type {
54 Ok(Unix { r#type, guid })
55 } else {
56 Err(UnixError::TypeMissing)
57 }
58 }
59}
60
61impl UnixType {
62 fn decode_path(path: &str) -> Result<UnixType, UnixError> {
63 let path = UnixType::Path(unescape(path)?);
64 Ok(path)
65 }
66
67 fn decode_dir(dir: &str) -> Result<UnixType, UnixError> {
68 let dir = UnixType::Dir(unescape(dir)?);
69 Ok(dir)
70 }
71
72 fn decode_tmpdir(tmpdir: &str) -> Result<UnixType, UnixError> {
73 let tmpdir = UnixType::Tmpdir(unescape(tmpdir)?);
74 Ok(tmpdir)
75 }
76
77 fn decode_abstract(abstract_: &str) -> Result<UnixType, UnixError> {
78 let abstract_ = UnixType::Abstract(unescape(abstract_)?);
79 Ok(abstract_)
80 }
81
82 fn decode_runtime(runtime: &str) -> Result<UnixType, UnixError> {
83 let runtime = unescape(runtime)?;
84 if &runtime == "yes" {
85 Ok(UnixType::Runtime)
86 } else {
87 Err(UnixError::UnknownRuntime)
88 }
89 }
90}
91
92impl TryFrom<&str> for UnixType {
93 type Error = UnixError;
94
95 fn try_from(server_address: &str) -> Result<Self, Self::Error> {
96 if let Some(path) = server_address.strip_prefix("path=") {
97 UnixType::decode_path(path)
98 } else if let Some(dir) = server_address.strip_prefix("dir=") {
99 UnixType::decode_dir(dir)
100 } else if let Some(tmpdir) = server_address.strip_prefix("tmpdir=") {
101 UnixType::decode_tmpdir(tmpdir)
102 } else if let Some(abstract_) = server_address.strip_prefix("abstract=") {
103 UnixType::decode_abstract(abstract_)
104 } else if let Some(runtime) = server_address.strip_prefix("runtime=") {
105 UnixType::decode_runtime(runtime)
106 } else {
107 Err(UnixError::UnknownKey)
108 }
109 }
110}