win_desktop_utils/paths.rs
1use std::fs;
2use std::path::PathBuf;
3
4use crate::error::{Error, Result};
5
6/// Returns the per-user roaming app-data directory for the given app name.
7///
8/// This function reads the `APPDATA` environment variable and appends `app_name`.
9/// It does not create the directory.
10///
11/// # Errors
12///
13/// Returns [`Error::InvalidInput`] if `app_name` is empty or whitespace only.
14/// Returns [`Error::Unsupported`] if `APPDATA` is not available.
15///
16/// # Examples
17///
18/// ```
19/// let path = win_desktop_utils::roaming_app_data("demo-app")?;
20/// assert!(path.ends_with("demo-app"));
21/// # Ok::<(), win_desktop_utils::Error>(())
22/// ```
23pub fn roaming_app_data(app_name: &str) -> Result<PathBuf> {
24 if app_name.trim().is_empty() {
25 return Err(Error::InvalidInput("app_name cannot be empty"));
26 }
27
28 let base = std::env::var_os("APPDATA").ok_or(Error::Unsupported("APPDATA is not set"))?;
29
30 Ok(PathBuf::from(base).join(app_name))
31}
32
33/// Returns the per-user local app-data directory for the given app name.
34///
35/// This function reads the `LOCALAPPDATA` environment variable and appends `app_name`.
36/// It does not create the directory.
37///
38/// # Errors
39///
40/// Returns [`Error::InvalidInput`] if `app_name` is empty or whitespace only.
41/// Returns [`Error::Unsupported`] if `LOCALAPPDATA` is not available.
42///
43/// # Examples
44///
45/// ```
46/// let path = win_desktop_utils::local_app_data("demo-app")?;
47/// assert!(path.ends_with("demo-app"));
48/// # Ok::<(), win_desktop_utils::Error>(())
49/// ```
50pub fn local_app_data(app_name: &str) -> Result<PathBuf> {
51 if app_name.trim().is_empty() {
52 return Err(Error::InvalidInput("app_name cannot be empty"));
53 }
54
55 let base =
56 std::env::var_os("LOCALAPPDATA").ok_or(Error::Unsupported("LOCALAPPDATA is not set"))?;
57
58 Ok(PathBuf::from(base).join(app_name))
59}
60
61/// Returns the roaming app-data directory for the given app name and creates it if needed.
62///
63/// This is equivalent to calling [`roaming_app_data`] and then `create_dir_all` on the result.
64///
65/// # Errors
66///
67/// Propagates errors from [`roaming_app_data`] and directory creation.
68///
69/// # Examples
70///
71/// ```
72/// let path = win_desktop_utils::ensure_roaming_app_data("demo-app")?;
73/// assert!(path.ends_with("demo-app"));
74/// assert!(path.exists());
75/// # Ok::<(), win_desktop_utils::Error>(())
76/// ```
77pub fn ensure_roaming_app_data(app_name: &str) -> Result<PathBuf> {
78 let path = roaming_app_data(app_name)?;
79 fs::create_dir_all(&path)?;
80 Ok(path)
81}
82
83/// Returns the local app-data directory for the given app name and creates it if needed.
84///
85/// This is equivalent to calling [`local_app_data`] and then `create_dir_all` on the result.
86///
87/// # Errors
88///
89/// Propagates errors from [`local_app_data`] and directory creation.
90///
91/// # Examples
92///
93/// ```
94/// let path = win_desktop_utils::ensure_local_app_data("demo-app")?;
95/// assert!(path.ends_with("demo-app"));
96/// assert!(path.exists());
97/// # Ok::<(), win_desktop_utils::Error>(())
98/// ```
99pub fn ensure_local_app_data(app_name: &str) -> Result<PathBuf> {
100 let path = local_app_data(app_name)?;
101 fs::create_dir_all(&path)?;
102 Ok(path)
103}