app_path/lib.rs
1//! # app-path
2//!
3//! Create portable applications that keep files together with the executable.
4//!
5//! ## Quick Start
6//!
7//! ```rust
8//! use app_path::AppPath;
9//!
10//! // Files relative to your executable
11//! let config = AppPath::new("config.toml");
12//! let database = AppPath::new("data/users.db");
13//! let logs = AppPath::new("logs/app.log");
14//!
15//! // Works like standard paths
16//! if config.exists() {
17//! let content = std::fs::read_to_string(&config)?;
18//! }
19//!
20//! // Create directories with clear intent
21//! logs.ensure_parent_dirs()?; // Creates logs/ directory for the file
22//! database.ensure_parent_dirs()?; // Creates data/ directory for the file
23//! # Ok::<(), Box<dyn std::error::Error>>(())
24//! ```
25//!
26//! ## Key Features
27//!
28//! - **Portable**: Relative paths resolve to executable directory
29//! - **System integration**: Absolute paths work as-is
30//! - **Zero dependencies**: Only standard library
31//! - **High performance**: Static caching, minimal allocations
32//! - **Thread-safe**: Concurrent access safe
33//!
34//! ## API Design
35//!
36//! - [`AppPath::new()`] - **Recommended**: Simple, infallible constructor
37//! - [`AppPath::try_new()`] - **Libraries**: Fallible version for error handling
38//! - [`AppPath::with_override()`] - **Deployment**: Environment-configurable paths
39//! - [`AppPath::ensure_parent_dirs()`] - **Files**: Creates parent directories for files
40//! - [`AppPath::ensure_dir_exists()`] - **Directories**: Creates directories (and parents)
41//! - [`exe_dir()`] - **Advanced**: Direct access to executable directory
42//!
43//! ## Panic Conditions
44//!
45//! [`AppPath::new()`] and [`exe_dir()`] panic only if executable location cannot be determined:
46//! - `std::env::current_exe()` fails (extremely rare)
47//! - Executable path is empty (system corruption)
48//!
49//! These represent unrecoverable system failures. For fallible behavior, use [`AppPath::try_new()`].
50
51mod app_path;
52mod error;
53mod functions;
54mod traits;
55
56#[cfg(test)]
57mod tests;
58
59// Re-export the public API
60pub use app_path::AppPath;
61pub use error::AppPathError;
62pub use functions::{exe_dir, try_exe_dir};
63
64/// Convenience macro for creating `AppPath` instances with optional environment variable overrides.
65///
66/// This macro provides a more ergonomic way to create `AppPath` instances, especially when
67/// dealing with environment variable overrides.
68///
69/// # Syntax
70///
71/// - `app_path!(path)` - Simple path creation (equivalent to `AppPath::new(path)`)
72/// - `app_path!(path, env = "VAR_NAME")` - With environment variable override
73/// - `app_path!(path, override = expression)` - With any optional override expression
74///
75/// # Examples
76///
77/// ```rust
78/// use app_path::{app_path, AppPath};
79///
80/// // Simple usage
81/// let config = app_path!("config.toml");
82/// assert_eq!(config.file_name().unwrap(), "config.toml");
83///
84/// // Environment variable override
85/// let data_dir = app_path!("data", env = "DATA_DIR");
86///
87/// // Custom override expression
88/// let log_file = app_path!("app.log", override = std::env::args().nth(1));
89/// ```
90#[macro_export]
91macro_rules! app_path {
92 ($path:expr) => {
93 $crate::AppPath::new($path)
94 };
95 ($path:expr, env = $env_var:expr) => {
96 $crate::AppPath::with_override($path, ::std::env::var($env_var).ok())
97 };
98 ($path:expr, override = $override_expr:expr) => {
99 $crate::AppPath::with_override($path, $override_expr)
100 };
101}