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
pub use app_directory::AppDirectory;
mod app_directory {
	use std::str::FromStr;

	use crate::prelude::*;

	/// Represents a path that points to a .app directory
	/// Exists for type-safety and to provide a consistent API
	#[derive(Debug, Serialize, Clone)]
	pub struct AppDirectory(Utf8PathBuf);

	impl AsRef<Utf8Path> for AppDirectory {
		fn as_ref(&self) -> &Utf8Path {
			self.0.as_ref()
		}
	}

	impl AsRef<std::path::Path> for AppDirectory {
		fn as_ref(&self) -> &std::path::Path {
			self.0.as_ref()
		}
	}

	impl FromStr for AppDirectory {
		type Err = Error;

		fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
			Self::new(s)
		}
	}

	impl<'de> serde::Deserialize<'de> for AppDirectory {
		fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
		where
			D: serde::Deserializer<'de>,
		{
			let string = String::deserialize(deserializer)?;
			AppDirectory::from_str(&string).map_err(serde::de::Error::custom)
		}
	}

	impl AppDirectory {
		/// # Safety
		/// Assets that the path exists, and points to a .app bundle directory
		unsafe fn new_unchecked(path: impl AsRef<Utf8Path>) -> Self {
			Self(Utf8PathBuf::from(path.as_ref()))
		}

		pub fn new(path: impl AsRef<Utf8Path>) -> Result<Self> {
			let path = path.as_ref();
			match path.try_exists() {
				Ok(true) => Ok(unsafe { Self::new_unchecked(path) }),
				Ok(false) => Err(Error::PathDoesNotExist {
					path: path.to_owned(),
					err: None,
				}),
				Err(err) => Err(Error::PathDoesNotExist {
					path: path.to_owned(),
					err: Some(err),
				}),
			}
		}

		pub fn get(&self) -> &Utf8Path {
			self.0.as_ref()
		}
	}
}