1#![doc(
8 html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png",
9 html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png"
10)]
11#![warn(missing_docs, rust_2018_idioms)]
12#![allow(clippy::deprecated_semver)]
13
14use std::{
15 ffi::OsString,
16 fmt::Display,
17 path::{Path, PathBuf},
18};
19
20use semver::Version;
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22
23pub mod acl;
24pub mod assets;
25pub mod config;
26pub mod config_v1;
27#[cfg(feature = "html-manipulation")]
28pub mod html;
29#[cfg(feature = "html-manipulation-2")]
30pub mod html2;
31pub mod io;
32pub mod mime_type;
33pub mod platform;
34pub mod plugin;
35#[cfg(feature = "resources")]
37pub mod resources;
38#[cfg(any(feature = "build", feature = "build-2"))]
39pub mod tokens;
40
41#[cfg(any(feature = "build", feature = "build-2"))]
42pub mod build;
43
44pub mod pattern;
46
47#[derive(Debug, Clone)]
49pub struct PackageInfo {
50 pub name: String,
52 pub version: Version,
54 pub authors: &'static str,
56 pub description: &'static str,
58 pub crate_name: &'static str,
60}
61
62#[allow(deprecated)]
63mod window_effects {
64 use super::*;
65
66 #[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
67 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
68 #[serde(rename_all = "camelCase")]
69 #[non_exhaustive]
70 pub enum WindowEffect {
72 #[deprecated(
74 since = "macOS 10.14",
75 note = "You should instead choose an appropriate semantic material."
76 )]
77 AppearanceBased,
78 #[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
80 Light,
81 #[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
83 Dark,
84 #[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
86 MediumLight,
87 #[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
89 UltraDark,
90 Titlebar,
92 Selection,
94 Menu,
96 Popover,
98 Sidebar,
100 HeaderView,
102 Sheet,
104 WindowBackground,
106 HudWindow,
108 FullScreenUI,
110 Tooltip,
112 ContentBackground,
114 UnderWindowBackground,
116 UnderPageBackground,
118 LiquidGlassRegular,
120 LiquidGlassClear,
122 Mica,
124 MicaDark,
126 MicaLight,
128 Tabbed,
130 TabbedDark,
132 TabbedLight,
134 Blur,
140 Acrylic,
146 }
147
148 #[derive(Debug, PartialEq, Eq, Clone, Copy, Deserialize, Serialize)]
152 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
153 #[serde(rename_all = "camelCase")]
154 pub enum WindowEffectState {
155 FollowsWindowActiveState,
157 Active,
159 Inactive,
161 }
162}
163
164pub use window_effects::{WindowEffect, WindowEffectState};
165
166#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)]
168#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
169#[non_exhaustive]
170pub enum TitleBarStyle {
171 #[default]
173 Visible,
174 Transparent,
178 Overlay,
185}
186
187impl Serialize for TitleBarStyle {
188 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
189 where
190 S: Serializer,
191 {
192 serializer.serialize_str(self.to_string().as_ref())
193 }
194}
195
196impl<'de> Deserialize<'de> for TitleBarStyle {
197 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
198 where
199 D: Deserializer<'de>,
200 {
201 let s = String::deserialize(deserializer)?;
202 Ok(match s.to_lowercase().as_str() {
203 "transparent" => Self::Transparent,
204 "overlay" => Self::Overlay,
205 _ => Self::Visible,
206 })
207 }
208}
209
210impl Display for TitleBarStyle {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 write!(
213 f,
214 "{}",
215 match self {
216 Self::Visible => "Visible",
217 Self::Transparent => "Transparent",
218 Self::Overlay => "Overlay",
219 }
220 )
221 }
222}
223
224#[derive(Debug, Copy, Clone, PartialEq, Eq)]
226#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
227#[non_exhaustive]
228pub enum Theme {
229 Light,
231 Dark,
233}
234
235impl Serialize for Theme {
236 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
237 where
238 S: Serializer,
239 {
240 serializer.serialize_str(self.to_string().as_ref())
241 }
242}
243
244impl<'de> Deserialize<'de> for Theme {
245 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
246 where
247 D: Deserializer<'de>,
248 {
249 let s = String::deserialize(deserializer)?;
250 Ok(match s.to_lowercase().as_str() {
251 "dark" => Self::Dark,
252 _ => Self::Light,
253 })
254 }
255}
256
257impl Display for Theme {
258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
259 write!(
260 f,
261 "{}",
262 match self {
263 Self::Light => "light",
264 Self::Dark => "dark",
265 }
266 )
267 }
268}
269
270#[derive(Debug, Clone)]
272#[non_exhaustive]
273pub struct Env {
274 #[cfg(target_os = "linux")]
276 pub appimage: Option<std::ffi::OsString>,
277 #[cfg(target_os = "linux")]
279 pub appdir: Option<std::ffi::OsString>,
280 pub args_os: Vec<OsString>,
282}
283
284#[allow(clippy::derivable_impls)]
285impl Default for Env {
286 fn default() -> Self {
287 let args_os = std::env::args_os().collect();
288 #[cfg(target_os = "linux")]
289 {
290 let env = Self {
291 #[cfg(target_os = "linux")]
292 appimage: std::env::var_os("APPIMAGE"),
293 #[cfg(target_os = "linux")]
294 appdir: std::env::var_os("APPDIR"),
295 args_os,
296 };
297 if env.appimage.is_some() || env.appdir.is_some() {
298 let is_temp = std::env::current_exe()
303 .map(|p| {
304 p.display()
305 .to_string()
306 .starts_with(&format!("{}/.mount_", std::env::temp_dir().display()))
307 })
308 .unwrap_or(true);
309
310 if !is_temp {
311 log::warn!(
312 "`APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue."
313 );
314 }
315 }
316 env
317 }
318 #[cfg(not(target_os = "linux"))]
319 {
320 Self { args_os }
321 }
322 }
323}
324
325pub type Result<T> = std::result::Result<T, Error>;
327
328#[derive(Debug, thiserror::Error)]
330#[non_exhaustive]
331pub enum Error {
332 #[error("Unable to determine target-architecture")]
334 Architecture,
335 #[error("Unable to determine target-os")]
337 Os,
338 #[error("Unable to determine target-environment")]
340 Environment,
341 #[error("Unsupported platform for reading resources")]
343 UnsupportedPlatform,
344 #[error("Could not get parent process")]
346 ParentProcess,
347 #[error("Could not get parent PID")]
349 ParentPid,
350 #[error("Could not get child process")]
352 ChildProcess,
353 #[error("{0}")]
355 Io(#[from] std::io::Error),
356 #[error("invalid pattern `{0}`. Expected either `brownfield` or `isolation`.")]
358 InvalidPattern(String),
359 #[cfg(feature = "resources")]
361 #[error("{0}")]
362 GlobPattern(#[from] glob::PatternError),
363 #[cfg(feature = "resources")]
365 #[error("`{0}`")]
366 Glob(#[from] glob::GlobError),
367 #[cfg(feature = "resources")]
369 #[error("glob pattern {0} path not found or didn't match any files.")]
370 GlobPathNotFound(String),
371 #[cfg(feature = "resources")]
373 #[error("{0}")]
374 WalkdirError(#[from] walkdir::Error),
375 #[cfg(feature = "resources")]
377 #[error(
378 "could not walk directory `{0}`, try changing `allow_walk` to true on the `ResourcePaths` constructor."
379 )]
380 NotAllowedToWalkDir(std::path::PathBuf),
381 #[cfg(feature = "resources")]
383 #[error("resource path `{0}` doesn't exist")]
384 ResourcePathNotFound(std::path::PathBuf),
385}
386
387pub fn display_path<P: AsRef<Path>>(p: P) -> String {
389 dunce::simplified(&p.as_ref().components().collect::<PathBuf>())
390 .display()
391 .to_string()
392}
393
394pub fn write_if_changed<P, C>(path: P, content: C) -> std::io::Result<()>
398where
399 P: AsRef<Path>,
400 C: AsRef<[u8]>,
401{
402 if std::fs::read(&path).is_ok_and(|existing| existing == content.as_ref()) {
403 return Ok(());
404 }
405
406 std::fs::write(path, content)
407}