1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
//! Unified directories for different use cases of an application, providing standard directories
//! for local development, when run as service or when run by a user.
//!
//! This crate provides 4 main structures of interest:
//!
//! - [`LocalDirs`](crate::LocalDirs) to use a local directory as basis.
//! - [`ServiceDirs`](crate::ServiceDirs) for use when running as a service.
//! - [`UserDirs`](crate::UserDirs) for use when run by a local user directly.
//! - [`UnifiedDirs`](crate::UnifiedDirs) as a combination of the above three to provide a common
//! interface.
//!
//! The simplest, but most opinionated, way of using this crate is the [`UnifiedDirs::simple`]
//! function. It will use the local dirs unconditionally in debug mode and uses several heuristics
//! to decide to use service or user dirs.
//!
//! Passing the boolean flag can be done in any way possible. It is very common to pass it from
//! command line arguments or use a environment variable to detect the service mode.
//!
//! ## Using the `simple` builder
//!
//! The call to [`UnifiedDirs::simple`] returns a [`SimpleBuilder`] that can be further configured
//! to use all or only specific heuristics to detect a service or user mode.
//!
//! ```rust
//! use unidirs::{Directories, UnifiedDirs};
//!
//! let dirs = UnifiedDirs::simple("com", "example", "app")
//! .with_env()
//! .with_args()
//! .with_username()
//! .build()
//! .unwrap();
//!
//! println!("cache dir: {}", dirs.cache_dir());
//! println!("config dir: {}", dirs.config_dir());
//! println!("data dir: {}", dirs.data_dir());
//!```
//!
//! ## Using `clap` to pass a flag
//!
//! This example uses the popular [`clap`](https://lib.rs/crates/clap) crate to parse and pass the
//! service flag to [`UnifiedDirs`].
//!
//! ```rust
//! use clap::Parser;
//! use unidirs::{Directories, UnifiedDirs};
//!
//! #[derive(Parser)]
//! struct Args {
//! #[arg(long, action, alias = "daemon")]
//! service: bool,
//! }
//!
//! let opt = Args::parse();
//! let dirs = UnifiedDirs::simple("com", "example", "app")
//! .with(|_| opt.service)
//! .build()
//! .unwrap();
//!
//! println!("cache dir: {}", dirs.cache_dir());
//! println!("config dir: {}", dirs.config_dir());
//! println!("data dir: {}", dirs.data_dir());
//! ```
//!
//! ## Using environment variables to detect service mode
//!
//! In this sample we use the environment variable `RUN_AS_SERVICE` to detect the service mode. The
//! variable can be anything, but pre-fixing it with the applications name is recommended to avoid
//! name clashes (for example `MYAPP_SERVICE`).
//!
//! ```rust
//! use std::env;
//!
//! use unidirs::{Directories, UnifiedDirs};
//!
//! let service = env::var_os("RUN_AS_SERVICE").is_some();
//! let dirs = UnifiedDirs::simple("com", "example", "app")
//! .with(|_| service)
//! .build()
//! .unwrap();
//!
//! println!("cache dir: {}", dirs.cache_dir());
//! println!("config dir: {}", dirs.config_dir());
//! println!("data dir: {}", dirs.data_dir());
//! ```
#![forbid(unsafe_code)]
#![deny(
missing_docs,
rust_2018_idioms,
clippy::all,
clippy::cargo,
clippy::pedantic,
clippy::expect_used,
clippy::unwrap_used
)]
#![allow(clippy::module_name_repetitions, clippy::multiple_crate_versions)]
pub use camino::{self, Utf8Path, Utf8PathBuf};
pub use crate::{
local::LocalDirs, service::ServiceDirs, simple::SimpleBuilder, unified::UnifiedDirs,
user::UserDirs,
};
mod local;
mod service;
mod simple;
mod unified;
mod user;
/// Common directories that are provided by all `*Dirs` structures. This can be used as an
/// alternative to [`UnifiedDirs`] to abstract over the underlying provider implementation.
///
/// Note that on some platforms the different directories can end up being the same.
pub trait Directories {
/// The cache directory is a location where an application can save any temporary data. The
/// contents can potentially be deleted by the system at any time. Therefore, the application
/// must be able to work without these files or be able to re-create them.
fn cache_dir(&self) -> &Utf8Path;
/// The config directory is where an application's settings are stored. These are usually
/// created by the user and loaded once at startup of the application.
fn config_dir(&self) -> &Utf8Path;
/// The data directory hold an application's state data, like a database. The folder is
/// expected to persist during the normal runtime of the OS.
fn data_dir(&self) -> &Utf8Path;
}