lib.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! Tauri utility helpers
  5. #![warn(missing_docs, rust_2018_idioms)]
  6. use std::fmt::Display;
  7. use semver::Version;
  8. use serde::{Deserialize, Deserializer, Serialize, Serializer};
  9. pub mod assets;
  10. pub mod config;
  11. pub mod html;
  12. pub mod io;
  13. pub mod platform;
  14. /// Prepare application resources and sidecars.
  15. #[cfg(feature = "resources")]
  16. pub mod resources;
  17. /// Application pattern.
  18. pub mod pattern;
  19. /// `tauri::App` package information.
  20. #[derive(Debug, Clone)]
  21. pub struct PackageInfo {
  22. /// App name
  23. pub name: String,
  24. /// App version
  25. pub version: Version,
  26. /// The crate authors.
  27. pub authors: &'static str,
  28. /// The crate description.
  29. pub description: &'static str,
  30. }
  31. impl PackageInfo {
  32. /// Returns the application package name.
  33. /// On macOS and Windows it's the `name` field, and on Linux it's the `name` in `kebab-case`.
  34. pub fn package_name(&self) -> String {
  35. #[cfg(target_os = "linux")]
  36. {
  37. use heck::ToKebabCase;
  38. self.name.clone().to_kebab_case()
  39. }
  40. #[cfg(not(target_os = "linux"))]
  41. self.name.clone()
  42. }
  43. }
  44. /// System theme.
  45. #[derive(Debug, Copy, Clone, PartialEq, Eq)]
  46. #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
  47. #[non_exhaustive]
  48. pub enum Theme {
  49. /// Light theme.
  50. Light,
  51. /// Dark theme.
  52. Dark,
  53. }
  54. impl Serialize for Theme {
  55. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  56. where
  57. S: Serializer,
  58. {
  59. serializer.serialize_str(self.to_string().as_ref())
  60. }
  61. }
  62. impl<'de> Deserialize<'de> for Theme {
  63. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  64. where
  65. D: Deserializer<'de>,
  66. {
  67. let s = String::deserialize(deserializer)?;
  68. Ok(match s.to_lowercase().as_str() {
  69. "dark" => Self::Dark,
  70. _ => Self::Light,
  71. })
  72. }
  73. }
  74. impl Display for Theme {
  75. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  76. write!(
  77. f,
  78. "{}",
  79. match self {
  80. Self::Light => "light",
  81. Self::Dark => "dark",
  82. }
  83. )
  84. }
  85. }
  86. /// Information about environment variables.
  87. #[derive(Debug, Clone)]
  88. #[non_exhaustive]
  89. pub struct Env {
  90. /// The APPIMAGE environment variable.
  91. #[cfg(target_os = "linux")]
  92. pub appimage: Option<std::ffi::OsString>,
  93. /// The APPDIR environment variable.
  94. #[cfg(target_os = "linux")]
  95. pub appdir: Option<std::ffi::OsString>,
  96. /// The command line arguments of the current process.
  97. pub args: Vec<String>,
  98. }
  99. #[allow(clippy::derivable_impls)]
  100. impl Default for Env {
  101. fn default() -> Self {
  102. let args = std::env::args().skip(1).collect();
  103. #[cfg(target_os = "linux")]
  104. {
  105. let env = Self {
  106. #[cfg(target_os = "linux")]
  107. appimage: std::env::var_os("APPIMAGE"),
  108. #[cfg(target_os = "linux")]
  109. appdir: std::env::var_os("APPDIR"),
  110. args,
  111. };
  112. if env.appimage.is_some() || env.appdir.is_some() {
  113. // validate that we're actually running on an AppImage
  114. // an AppImage is mounted to `/$TEMPDIR/.mount_${appPrefix}${hash}`
  115. // see https://github.com/AppImage/AppImageKit/blob/1681fd84dbe09c7d9b22e13cdb16ea601aa0ec47/src/runtime.c#L501
  116. // note that it is safe to use `std::env::current_exe` here since we just loaded an AppImage.
  117. let is_temp = std::env::current_exe()
  118. .map(|p| {
  119. p.display()
  120. .to_string()
  121. .starts_with(&format!("{}/.mount_", std::env::temp_dir().display()))
  122. })
  123. .unwrap_or(true);
  124. if !is_temp {
  125. panic!("`APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue.");
  126. }
  127. }
  128. env
  129. }
  130. #[cfg(not(target_os = "linux"))]
  131. {
  132. Self { args }
  133. }
  134. }
  135. }
  136. /// The result type of `tauri-utils`.
  137. pub type Result<T> = std::result::Result<T, Error>;
  138. /// The error type of `tauri-utils`.
  139. #[derive(Debug, thiserror::Error)]
  140. #[non_exhaustive]
  141. pub enum Error {
  142. /// Target triple architecture error
  143. #[error("Unable to determine target-architecture")]
  144. Architecture,
  145. /// Target triple OS error
  146. #[error("Unable to determine target-os")]
  147. Os,
  148. /// Target triple environment error
  149. #[error("Unable to determine target-environment")]
  150. Environment,
  151. /// Tried to get resource on an unsupported platform
  152. #[error("Unsupported platform for reading resources")]
  153. UnsupportedPlatform,
  154. /// Get parent process error
  155. #[error("Could not get parent process")]
  156. ParentProcess,
  157. /// Get parent process PID error
  158. #[error("Could not get parent PID")]
  159. ParentPid,
  160. /// Get child process error
  161. #[error("Could not get child process")]
  162. ChildProcess,
  163. /// IO error
  164. #[error("{0}")]
  165. Io(#[from] std::io::Error),
  166. /// Invalid pattern.
  167. #[error("invalid pattern `{0}`. Expected either `brownfield` or `isolation`.")]
  168. InvalidPattern(String),
  169. /// Invalid glob pattern.
  170. #[cfg(feature = "resources")]
  171. #[error("{0}")]
  172. GlobPattern(#[from] glob::PatternError),
  173. /// Failed to use glob pattern.
  174. #[cfg(feature = "resources")]
  175. #[error("`{0}`")]
  176. Glob(#[from] glob::GlobError),
  177. /// Glob pattern did not find any results.
  178. #[cfg(feature = "resources")]
  179. #[error("path matching {0} not found.")]
  180. GlobPathNotFound(String),
  181. /// Error walking directory.
  182. #[cfg(feature = "resources")]
  183. #[error("{0}")]
  184. WalkdirError(#[from] walkdir::Error),
  185. /// Not allowed to walk dir.
  186. #[cfg(feature = "resources")]
  187. #[error("could not walk directory `{0}`, try changing `allow_walk` to true on the `ResourcePaths` constructor.")]
  188. NotAllowedToWalkDir(std::path::PathBuf),
  189. }
  190. /// Suppresses the unused-variable warnings of the given inputs.
  191. ///
  192. /// This does not move any values. Instead, it just suppresses the warning by taking a
  193. /// reference to the value.
  194. #[macro_export]
  195. macro_rules! consume_unused_variable {
  196. ($($arg:expr),*) => {
  197. $(
  198. let _ = &$arg;
  199. )*
  200. ()
  201. };
  202. }
  203. /// Prints to the standard error, with a newline.
  204. ///
  205. /// Equivalent to the [`eprintln!`] macro, except that it's only effective for debug builds.
  206. #[macro_export]
  207. macro_rules! debug_eprintln {
  208. () => ($crate::debug_eprintln!(""));
  209. ($($arg:tt)*) => {
  210. #[cfg(debug_assertions)]
  211. eprintln!($($arg)*);
  212. #[cfg(not(debug_assertions))]
  213. $crate::consume_unused_variable!($($arg)*);
  214. };
  215. }