Expand description
§app-path
Create portable applications that keep files together with the executable.
§Quick Start
use app_path::app_path;
// Files relative to your executable - not current directory!
let config = app_path!("config.toml"); // → /path/to/exe_dir/config.toml
let database = app_path!("data/users.db"); // → /path/to/exe_dir/data/users.db
// Environment overrides for deployment
let logs = app_path!("logs/app.log", env = "LOG_PATH");
// → Uses LOG_PATH if set, otherwise /path/to/exe_dir/logs/app.log
// Works like standard paths - all Path methods available
if config.exists() {
let content = std::fs::read_to_string(&config)?;
}
// Directory creation
logs.create_parents()?; // Creates logs/ directory for the file
app_path!("cache").create_dir()?; // Creates cache/ directory itself
§Key Features
- Portable: Relative paths resolve to executable directory
- System integration: Absolute paths work as-is
- Zero dependencies: Only standard library
- High performance: Static caching, minimal allocations
- Thread-safe: Concurrent access safe
- Zero-cost: All
Path
methods available viaDeref
(e.g.,exists()
,is_file()
,extension()
)
§API Design
§Constructors
AppPath::new()
- Application base directory: Returns the directory containing the executableAppPath::with()
- Primary API: Create paths relative to application base directoryAppPath::try_new()
- Libraries: Fallible version for getting application base directoryAppPath::try_with()
- Libraries: Fallible version for creating relative pathsAppPath::with_override()
- Deployment: Environment-configurable pathsAppPath::try_with_override()
- Deployment (Fallible): Fallible environment-configurable pathsAppPath::with_override_fn()
- Advanced: Function-based override logicAppPath::try_with_override_fn()
- Advanced (Fallible): Fallible function-based override logic
§Directory Creation
AppPath::create_parents()
- Files: Creates parent directories for filesAppPath::create_dir()
- Directories: Creates directories (and parents)
§Path Operations & Traits
- All
Path
methods: Available directly viaDeref<Target=Path>
(e.g.,exists()
,is_file()
,file_name()
,extension()
) AppPath::into_path_buf()
- Conversion: Extract ownedPathBuf
from wrapperAppPath::into_inner()
- Conversion: Alias forinto_path_buf()
following Rust patternsAppPath::to_bytes()
- Ecosystem: Raw bytes for specialized librariesAppPath::into_bytes()
- Ecosystem: Owned bytes for specialized libraries
§Convenience Macros
app_path!
- Macro: Convenient syntax with optional environment overridestry_app_path!
- Macro (Fallible): ReturnsResult
for explicit error handling
§Constructor Variants
This crate provides both panicking and fallible variants for most operations:
Panicking (Recommended) | Fallible (Libraries) | Use Case |
---|---|---|
AppPath::new() | AppPath::try_new() | Get application base directory |
AppPath::with() | AppPath::try_with() | Create relative paths |
AppPath::with_override() | AppPath::try_with_override() | Environment-configurable paths |
AppPath::with_override_fn() | AppPath::try_with_override_fn() | Function-based override logic |
app_path! | try_app_path! | Convenient macros |
§Macro Syntax Variants
Both app_path!
and try_app_path!
macros support four syntax forms for maximum flexibility:
// 1. Direct value
let config = app_path!("config.toml");
// → /path/to/exe_dir/config.toml
// 2. With environment override
let config = app_path!("config.toml", env = "CONFIG_PATH");
// → Uses CONFIG_PATH if set, otherwise /path/to/exe_dir/config.toml
// 3. With optional override value
let config = app_path!("config.toml", override = std::env::var("CONFIG_PATH").ok());
// → Uses CONFIG_PATH if available, otherwise /path/to/exe_dir/config.toml
// 4. With function-based override
let config = app_path!("config.toml", fn = || {
std::env::var("CONFIG_PATH").ok()
});
// → Uses function result if Some, otherwise /path/to/exe_dir/config.toml
§Variable Capturing in Macros
Both macros support variable capturing in complex expressions:
let version = "1.0";
let cache = app_path!(format!("cache-{version}"));
let user_ids = vec![123, 456];
let logs: Vec<_> = user_ids.iter()
.map(|id| app_path!(format!("logs/user-{id}.log")))
.collect();
§Ecosystem Integration
AppPath works seamlessly with ecosystem crates through Deref<Target=Path>
:
§Serde Integration
use app_path::app_path;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Config {
db_path: String,
}
let config = Config {
db_path: app_path!("data/app.db").display().to_string(),
};
§UTF-8 Path Serialization (camino)
use app_path::app_path;
use camino::Utf8PathBuf;
let static_dir = app_path!("web/static");
let utf8_static = Utf8PathBuf::from_path_buf(static_dir.into_path_buf())
.map_err(|_| "Invalid UTF-8 path")?;
§Cross-Platform Path Types (typed-path)
use app_path::app_path;
use typed_path::{WindowsPath, UnixPath};
let dist_dir = app_path!("dist");
let win_path = WindowsPath::new(&dist_dir.to_bytes());
let unix_path = UnixPath::new(&dist_dir.to_bytes());
§Panic Conditions
AppPath::new()
panics only if executable location cannot be determined:
std::env::current_exe()
fails (extremely rare system failure)- Executable path is empty (indicates system corruption)
These represent unrecoverable system failures that occur at application startup. After the first successful call, the executable directory is cached and subsequent calls never panic.
For libraries or applications requiring graceful error handling, use the fallible
variant AppPath::try_new()
instead.
Macros§
- app_
path - Convenience macro for creating
AppPath
instances with optional environment variable overrides. - try_
app_ path - Fallible version of
app_path!
that returns aResult
instead of panicking.
Structs§
- AppPath
- Creates paths relative to the executable location for portable applications.
Enums§
- AppPath
Error - Error type for AppPath operations.