dbus_server_address_parser/decode/
unix.rs

1use 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}