edifact_mapper/data_dir.rs
1//! Data directory configuration for locating DataBundle files on disk.
2
3use std::path::{Path, PathBuf};
4
5/// Configures where the [`Mapper`](crate::Mapper) looks for `DataBundle` files.
6///
7/// Bundle files follow the naming convention `edifact-data-{FV}.bin`
8/// (e.g., `edifact-data-FV2504.bin`).
9///
10/// # Resolution order for [`DataDir::auto`]
11///
12/// 1. `$EDIFACT_DATA_DIR` environment variable (if set)
13/// 2. `$HOME/.edifact/data` (Unix) or `%USERPROFILE%\.edifact\data` (Windows)
14/// 3. `./data` (current working directory fallback)
15#[derive(Debug, Clone)]
16pub struct DataDir {
17 path: PathBuf,
18 eager_fvs: Vec<String>,
19}
20
21impl DataDir {
22 /// Auto-detect the data directory from the environment.
23 ///
24 /// See [struct-level docs](DataDir) for resolution order.
25 pub fn auto() -> Self {
26 let path = if let Ok(env_dir) = std::env::var("EDIFACT_DATA_DIR") {
27 PathBuf::from(env_dir)
28 } else if let Some(home) = home_dir() {
29 home.join(".edifact").join("data")
30 } else {
31 PathBuf::from("data")
32 };
33 Self {
34 path,
35 eager_fvs: vec![],
36 }
37 }
38
39 /// Use an explicit path for the data directory.
40 pub fn path<P: AsRef<Path>>(path: P) -> Self {
41 Self {
42 path: path.as_ref().to_path_buf(),
43 eager_fvs: vec![],
44 }
45 }
46
47 /// Mark format versions to be eagerly loaded when the [`Mapper`](crate::Mapper)
48 /// is created (rather than lazy-loaded on first access).
49 pub fn eager(mut self, fvs: &[&str]) -> Self {
50 self.eager_fvs = fvs.iter().map(|s| s.to_string()).collect();
51 self
52 }
53
54 /// The resolved data directory path.
55 pub fn data_path(&self) -> &Path {
56 &self.path
57 }
58
59 /// Format versions that should be eagerly loaded.
60 pub fn eager_fvs(&self) -> &[String] {
61 &self.eager_fvs
62 }
63
64 /// Path to the bundle file for a specific format version.
65 pub fn bundle_path(&self, fv: &str) -> PathBuf {
66 self.path.join(format!("edifact-data-{fv}.bin"))
67 }
68}
69
70fn home_dir() -> Option<PathBuf> {
71 std::env::var("HOME")
72 .or_else(|_| std::env::var("USERPROFILE"))
73 .ok()
74 .map(PathBuf::from)
75}