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