app-path 0.2.0

Create file paths relative to your executable for truly portable applications
Documentation
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
# AppPath

**Create paths relative to your executable for truly portable applications.**

[![Crates.io](https://img.shields.io/crates/v/app-path.svg)](https://crates.io/crates/app-path)
[![Documentation](https://docs.rs/app-path/badge.svg)](https://docs.rs/app-path)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT)
[![CI](https://github.com/DK26/app-path-rs/workflows/CI/badge.svg)](https://github.com/DK26/app-path-rs/actions)

## 🎯 The Problem

When building applications that need to access files (configs, templates, data), you typically have two choices:

1. **System directories** (`~/.config/`, `%APPDATA%`, etc.) - Great for installed apps, but...
   - Requires installation
   - Spreads files across the system
   - Hard to backup/move
   - Needs admin rights on some systems

2. **Hardcoded paths** - Simple but brittle and non-portable

## ✨ The Solution

**AppPath creates paths relative to your executable location**, enabling truly portable applications where everything stays together.

```rust
use app_path::AppPath;
use std::path::PathBuf;

// Create paths relative to your executable - simple and clean
let config = AppPath::new("config.toml");
let data = AppPath::new("data/users.db");

// Accepts any AsRef<Path> type - no unnecessary allocations
let log_file = "logs/app.log".to_string();
let logs = AppPath::new(&log_file);

let path_buf = PathBuf::from("cache/data.bin");
let cache = AppPath::new(&path_buf);

// Works with any path-like type
let from_path = AppPath::new(std::path::Path::new("temp.txt"));

// Alternative: Use From for any path type
let settings: AppPath = "settings.json".into();
let data_file: AppPath = PathBuf::from("data.db").into();

// Absolute paths are used as-is (for system integration)
let system_log = AppPath::new("/var/log/app.log");
let windows_temp = AppPath::new(r"C:\temp\cache.dat");

// Get the paths for use with standard library functions
println!("Config: {}", config.path().display());
println!("Data: {}", data.path().display());

// Check existence and create directories
if !logs.exists() {
    logs.create_dir_all().unwrap();
}
```

## 🚀 Features & Design Philosophy

AppPath is built around the core principle of **portable-first design** with these key features:

- 🚀 **Zero dependencies** - Uses only standard library for maximum compatibility
- 🌍 **Cross-platform** - Consistent behavior across Windows, Linux, and macOS
- 🛡️ **Infallible API** - Simple `new()` constructor that panics on rare system failures (with clear documentation of edge cases)
- 🚀 **Static caching** - Executable location determined once and cached for performance
- 🔧 **Easy testing** - Use standard path joining for custom layouts
- 📁 **Smart path handling** - Relative paths resolve to executable directory, absolute paths used as-is
-**Zero allocations** - Accepts `impl AsRef<Path>` to avoid unnecessary allocations
- 🎯 **Ergonomic conversions** - `From` implementations for all common path types
- 📚 **Comprehensive docs** - Extensive examples and clear API documentation

### Design Principles

**1. Simplicity Over Complexity**
- Infallible API eliminates error handling boilerplate from every usage site
- Single `new()` method accepts all path types through `AsRef<Path>`
- Clear panic conditions for the rare failure cases

**2. Performance by Design**
- Static caching of executable location (determined once, used forever)
- Zero-allocation API design through efficient borrowing
- Minimal memory footprint (only stores resolved path)

**3. Portable-First Architecture**
- Everything stays together with your executable by default
- Enables true application portability across environments
- Smart path resolution supports both portable and system integration use cases

**4. Robust Edge Case Handling**
- Works in containerized and jailed environments
- Handles root-level executables gracefully
- Clear failure modes with descriptive error messages

## � Trait Implementations & Ergonomics

`AppPath` implements standard traits for seamless integration with Rust APIs:

**Collections & Comparison:**
- `PartialEq`, `Eq`, `Hash` - Use in `HashMap`, `HashSet`
- `PartialOrd`, `Ord` - Automatic sorting in `BTreeMap`, `BTreeSet`

**Path Integration:**
- `AsRef<Path>` - Works with any API expecting `&Path`
- `Deref<Target=Path>` - Call `Path` methods directly (e.g., `.extension()`)
- `Borrow<Path>` - Efficient lookups in collections

**Conversions:**
- `From<T>` for `&str`, `String`, `&Path`, `PathBuf`
- `Into<PathBuf>` - Convert back to owned `PathBuf`
- `Clone`, `Debug`, `Display`, `Default`

```rust
use app_path::AppPath;
use std::collections::HashMap;

// Works in collections
let mut files = HashMap::new();
files.insert(AppPath::new("config.toml"), "Configuration");

// Direct Path methods via Deref
let config = AppPath::new("config.toml");
assert_eq!(config.extension(), Some("toml".as_ref()));

// Natural conversions
let path: AppPath = "data.txt".into();
```

## �📁 Path Resolution Behavior

`AppPath` handles different path types intelligently:

### Relative Paths (Recommended for Portable Apps)
```rust
// These resolve relative to your executable's directory
let config = AppPath::new("config.toml");       // → exe_dir/config.toml
let data = AppPath::new("data/users.db");       // → exe_dir/data/users.db
let nested = AppPath::new("logs/app/debug.log"); // → exe_dir/logs/app/debug.log
```

### Absolute Paths (For System Integration)
```rust
// These are used as-is, ignoring the executable directory
let system_config = AppPath::new("/etc/myapp/config.toml");  // → /etc/myapp/config.toml
let windows_temp = AppPath::new(r"C:\temp\cache.dat");       // → C:\temp\cache.dat
let user_home = AppPath::new("/home/user/.myapp/settings");  // → /home/user/.myapp/settings
```

This design allows your application to:
- **Stay portable** with relative paths for app-specific files
-**Integrate with system** using absolute paths when needed
-**Be configurable** - users can specify either type in config files

## 📖 Quick Start

Add to your `Cargo.toml`:
```toml
[dependencies]
app-path = "0.2.0"
```

```rust
use app_path::AppPath;
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create paths relative to your executable - simple and clean
    let config = AppPath::new("config.toml");
    let templates = AppPath::new("templates");
    let logs = AppPath::new("logs/app.log");
    
    // Use them like normal paths
    if config.exists() {
        let content = fs::read_to_string(config.path())?;
        println!("Config: {}", content);
    }
    
    // Create directories automatically
    logs.create_dir_all()?;
    fs::write(logs.path(), "Application started\n")?;
    
    println!("Config: {}", config);      // Displays full path
    println!("Templates: {}", templates);
    
    Ok(())
}
```

## � Additional Helper Functions

### The `exe_dir()` Function

For cases where you need direct access to your executable's directory:

```rust
use app_path::exe_dir;

fn main() {
    // Get the directory containing your executable
    let exe_directory = exe_dir();
    println!("Executable directory: {}", exe_directory.display());
    
    // Use it with standard library functions
    for entry in std::fs::read_dir(exe_directory).unwrap() {
        println!("Found: {}", entry.unwrap().path().display());
    }
    
    // Or combine with custom logic
    let custom_path = exe_directory.join("custom").join("path.txt");
    println!("Custom path: {}", custom_path.display());
}
```

**When to use `exe_dir()` vs `AppPath`:**
- Use `AppPath::new()` for most file/directory access (recommended)
- Use `exe_dir()` when you need the raw directory for custom path manipulation
- Use `exe_dir()` when interfacing with APIs that expect `&Path` directories

## �🚨 Panic Conditions & Design Rationale

AppPath uses an **infallible API** by design. This is a deliberate architectural choice that prioritizes **simplicity and performance** for the common case where executable location determination succeeds (which is the vast majority of real-world usage).

### Why Infallible Instead of Fallible?

**The Problem with Fallible APIs:**
- Every single usage site must handle potential errors
- Results in verbose, repetitive error handling code
- Encourages poor practices like `.unwrap()` or `.expect()`
- Creates cognitive overhead for developers

**The AppPath Solution:**
- **Executable location determination succeeds >99.9% of the time** in real applications
- **When it fails, it indicates fundamental system issues** that are typically unrecoverable
- **Clean, simple API** eliminates boilerplate and improves code readability
- **Clear panic conditions** are well-documented with specific failure scenarios

### When AppPath Panics

The crate will panic during **static initialization** (first use) if:

- **Cannot determine executable location** - When `std::env::current_exe()` fails
  - Rare, but possible in some embedded or heavily sandboxed environments
  - Indicates the system cannot provide basic process information
- **Executable path is empty** - When the system returns an empty executable path
  - Extremely rare, indicates a broken/corrupted system state

### Edge Cases We Handle

**Root-level executables:** When executable runs at filesystem root (e.g., `/init`, `C:\`), AppPath uses the root directory itself as the base directory.

**Containerized environments:** Designed to work correctly in Docker, chroot, and other containerized environments.

**Jailed environments:** Handles various forms of process isolation and sandboxing.

### For Applications Requiring Fallible Behavior

If your application needs to handle executable location failures gracefully:

```rust
use app_path::AppPath;
use std::env;

fn safe_app_path(relative_path: &str) -> AppPath {
    match env::current_exe() {
        Ok(exe_path) => {
            if let Some(exe_dir) = exe_path.parent() {
                let config_path = exe_dir.join(relative_path);
                AppPath::new(config_path)
            } else {
                // Fallback for edge case where exe has no parent
                let temp_dir = env::temp_dir().join("myapp");
                let _ = std::fs::create_dir_all(&temp_dir);
                let config_path = temp_dir.join(relative_path);
                AppPath::new(config_path)
            }
        }
        Err(_) => {
            // Fallback when executable location cannot be determined
            let temp_dir = env::temp_dir().join("myapp");
            let _ = std::fs::create_dir_all(&temp_dir);
            let config_path = temp_dir.join(relative_path);
            AppPath::new(config_path)
        }
    }
}

// Usage with fallback strategy
let config = safe_app_path("config.toml");
```

**Note:** Using `std::env::current_exe()` directly is simpler and more idiomatic than `panic::catch_unwind` patterns. Most applications should use environment variable fallbacks or conditional patterns instead.
```

## ⚡ Efficient API Design

AppPath is designed for practical, efficient usage:

**Key Design Features:**
- **Static caching** - Executable location determined once, cached forever
- **Zero allocations** - String literals and references used efficiently  
- **Minimal memory** - Only stores the final resolved path
- **Optimized methods** - Zero-cost abstractions for direct path operations

```rust
use app_path::AppPath;

// Efficient - no allocations
let config = AppPath::new("config.toml");          // &str
let data = AppPath::new(&filename);                 // &String (no move)

// Direct ownership transfer when desired
let cache: AppPath = PathBuf::from("cache.json").into(); // PathBuf moved
```

## 🏗️ Application Structure

Your portable application structure becomes:
```
myapp.exe          # Your executable
├── config.toml    # AppPath::new("config.toml")
├── templates/     # AppPath::new("templates")
│   ├── email.html
│   └── report.html
├── data/          # AppPath::new("data")
│   └── cache.db
└── logs/          # AppPath::new("logs")
    └── app.log
```

## 🧪 Testing Support

Use standard path joining for testing with custom directories:

```rust
#[cfg(test)]
mod tests {
    use app_path::AppPath;
    use std::env;

    #[test]
    fn test_config_loading() {
        let temp = env::temp_dir().join("app_path_test");
        let config_path = temp.join("config.toml");
        let config = AppPath::new(config_path);
        
        // Test with isolated temporary directory
        assert!(!config.exists());
    }
}
```

## 🎯 Why Choose AppPath?

### vs. Standard Library (`std::env::current_dir()`)
```rust
// ❌ Brittle - depends on where user runs the program
let config = std::env::current_dir()?.join("config.toml");

// ✅ Reliable - always relative to your executable
let config = AppPath::new("config.toml");
```

### vs. System Directories (`directories` crate)
```rust
// ❌ Scattered across the system
use directories::ProjectDirs;
let proj_dirs = ProjectDirs::from("com", "MyOrg", "MyApp").unwrap();
let config = proj_dirs.config_dir().join("config.toml"); // ~/.config/MyApp/config.toml

// ✅ Everything together with your app
let config = AppPath::new("config.toml"); // ./config.toml (next to exe)
```

### vs. Manual Path Joining
```rust
// ❌ Verbose and error-prone
let exe_path = std::env::current_exe()?;
let exe_dir = exe_path.parent().ok_or("No parent")?;
let config = exe_dir.join("config.toml");

// ✅ Clean and simple
let config = AppPath::new("config.toml");
```

## 📁 Primary Use Cases & Value Proposition

AppPath is specifically designed to excel in scenarios where **portable, self-contained applications** provide significant value:

### 🎯 Core Use Cases

**1. Portable Applications**
- **USB/Flash drive applications** that users carry between computers
- **Network share deployments** where applications run from shared directories
- **Zero-installation tools** that work immediately after download
- **Backup and migration friendly** - entire application state moves together

**2. Development and DevOps Tools**
- **CLI utilities** that should work anywhere without setup
- **Build tools** that teams can share without environment setup
- **Deployment scripts** that bundle their configuration
- **Development environments** that are fully self-contained

**3. Corporate and Enterprise**
- **Restricted environments** where users can't install software system-wide
- **Compliance requirements** where software must be contained
- **Auditing scenarios** where all application files must be in one location
- **Temporary usage** where applications are run briefly and then removed

**4. Embedded and Specialized Systems**
- **Embedded applications** with simple, predictable file layouts
- **Kiosk systems** where everything must be self-contained
- **Appliance software** that shouldn't scatter files across the system
- **Single-purpose systems** with minimal filesystem complexity

### 💡 Why These Use Cases Matter

**Traditional approaches fail in these scenarios:**

```rust
// ❌ Current directory dependency - breaks portability
let config = std::env::current_dir()?.join("config.toml");
// Problem: Depends on where user runs the program from

// ❌ System directories - requires installation
use directories::ProjectDirs;
let proj_dirs = ProjectDirs::from("com", "MyOrg", "MyApp").unwrap();
let config = proj_dirs.config_dir().join("config.toml");
// Problem: Scatters files across system, needs installation

// ❌ Manual executable path handling - verbose and error-prone
let exe_path = std::env::current_exe()?;
let exe_dir = exe_path.parent().ok_or("No parent")?;
let config = exe_dir.join("config.toml");
// Problem: Repetitive boilerplate, easy to get wrong

// ✅ AppPath - designed for portability
let config = AppPath::new("config.toml");
// Solution: Always relative to executable, simple API, works everywhere
```

### 🏆 Success Stories

**Perfect for applications like:**
- **Postman** - Portable API testing tool
- **Sublime Text Portable** - Editor that runs from USB drives
- **PortableApps.com** ecosystem - Hundreds of portable applications
- **Docker deployment tools** - Self-contained utilities
- **Game development tools** - Asset processors and build tools
- **System administration utilities** - Tools that work on any system

### 🚀 Strengthening Your Application's Value

AppPath enables you to build applications that users **love** because they:

1. **Just Work** - No installation, no setup, no configuration
2. **Are Reliable** - Don't break when moved or copied
3. **Are Predictable** - All files in one place, easy to backup/restore
4. **Are Respectful** - Don't scatter files across the user's system
5. **Are Portable** - Work identically across different machines and environments

## 🎯 API Design Philosophy

AppPath's API is carefully crafted around specific design principles that prioritize **developer experience** and **real-world usability**:

### 1. **Simplicity Over Configurability**

**Design Choice:** Single `new()` method that accepts `impl AsRef<Path>`

**Why:** Instead of multiple constructors (`new_str()`, `new_path()`, `new_pathbuf()`), we provide one method that works with all path types. This reduces cognitive load and API surface area.

```rust
// ✅ Simple, unified API
let config = AppPath::new("config.toml");          // &str
let data = AppPath::new(PathBuf::from("data.db")); // PathBuf
let logs = AppPath::new(Path::new("logs.txt"));    // &Path

// ❌ What we avoided: Multiple constructors
// let config = AppPath::new_str("config.toml");
// let data = AppPath::new_pathbuf(PathBuf::from("data.db"));
// let logs = AppPath::new_path(Path::new("logs.txt"));
```

### 2. **Performance Through Zero-Allocation Design**

**Design Choice:** `impl AsRef<Path>` instead of `impl Into<PathBuf>`

**Why:** Avoids unnecessary allocations for the common case of string literals and borrowed paths.

```rust
// ✅ Zero allocations for common cases
let config = AppPath::new("config.toml");    // No allocation - borrows string literal
let data = AppPath::new(&some_path_string);  // No allocation - borrows existing string

// ❌ What we avoided: Unnecessary allocations
// impl Into<PathBuf> would always allocate for string literals
```

### 3. **Ergonomic Conversions**

**Design Choice:** `From` trait implementations for all common path types

**Why:** Enables natural, idiomatic Rust conversions while maintaining type safety.

```rust
// ✅ Natural conversions
let config: AppPath = "config.toml".into();
let data: AppPath = PathBuf::from("data.db").into();

// Works seamlessly with functions expecting AppPath
fn process_config(path: impl Into<AppPath>) {
    let app_path = path.into();
    // ...
}

process_config("config.toml");  // &str
process_config(PathBuf::from("data.db"));  // PathBuf
```

### 4. **Clear Mental Model**

**Design Choice:** Smart path resolution (relative vs absolute)

**Why:** Provides intuitive behavior that matches user expectations for portable applications.

```rust
// ✅ Intuitive behavior
let portable_config = AppPath::new("config.toml");        // Relative to exe
let system_config = AppPath::new("/etc/myapp/config");    // Absolute path preserved

// Users understand: relative = portable, absolute = system integration
```

### 5. **Testability by Design**

**Design Choice:** Simple path joining for testing

**Why:** Enables easy testing without requiring complex methods.

```rust
// ✅ Easy testing
#[test]
fn test_config_handling() {
    let temp_dir = std::env::temp_dir().join("test");
    let config_path = temp_dir.join("config.toml");
    let config = AppPath::new(config_path);
    // Test in isolation...
}
```

### 6. **Minimal Memory Footprint**

**Design Choice:** Store only the resolved path

**Why:** Applications often create many AppPath instances. Storing only the final path minimizes memory usage.

```rust
// ✅ Minimal memory usage
// AppPath only stores the resolved PathBuf
struct AppPath {
    full_path: PathBuf,  // Only field
}

// ❌ What we avoided: Storing redundant data
// struct AppPath {
//     input_path: PathBuf,   // Redundant
//     full_path: PathBuf,    // What we actually need
// }
```

### 7. **Fail-Fast Philosophy**

**Design Choice:** Panic on initialization failure

**Why:** Executable location determination failing indicates fundamental system issues that are typically unrecoverable. Panicking fails fast with clear error messages.

```rust
// ✅ Clear failure mode
// Panics immediately with descriptive message if system is broken
let config = AppPath::new("config.toml");

// ❌ What we avoided: Error handling burden
// Result<AppPath, Error> would require handling at every usage site
// when failure cases are extremely rare and typically unrecoverable
```

## 🔄 Common Patterns & Best Practices

### 1. **Configuration File Pattern**

```rust
use app_path::AppPath;
use std::fs;

fn load_config() -> Result<Config, Box<dyn std::error::Error>> {
    let config_path = AppPath::new("config.toml");
    
    let config_content = if config_path.exists() {
        fs::read_to_string(config_path.path())?
    } else {
        // Create default config
        let default_config = include_str!("default_config.toml");
        config_path.create_dir_all()?;
        fs::write(config_path.path(), default_config)?;
        default_config.to_string()
    };
    
    Ok(toml::from_str(&config_content)?)
}
```

### 2. **Data Directory Pattern**

```rust
use app_path::AppPath;

fn ensure_data_directory() -> Result<AppPath, std::io::Error> {
    let data_dir = AppPath::new("data");
    data_dir.create_dir_all()?;
    Ok(data_dir)
}

fn get_user_database() -> AppPath {
    AppPath::new("data/users.db")
}

fn get_cache_file(name: &str) -> AppPath {
    AppPath::new(format!("data/cache/{}", name))
}
```

### 3. **Logging Setup Pattern**

```rust
use app_path::AppPath;
use std::fs::OpenOptions;

fn setup_logging() -> Result<(), Box<dyn std::error::Error>> {
    let log_file = AppPath::new("logs/app.log");
    log_file.create_dir_all()?;
    
    let log_file = OpenOptions::new()
        .create(true)
        .append(true)
        .open(log_file.path())?;
    
    // Configure your logging framework to use log_file
    Ok(())
}
```

### 4. **Plugin Directory Pattern**

```rust
use app_path::AppPath;
use std::fs;

fn load_plugins() -> Result<Vec<Plugin>, Box<dyn std::error::Error>> {
    let plugins_dir = AppPath::new("plugins");
    
    if !plugins_dir.exists() {
        return Ok(Vec::new());
    }
    
    let mut plugins = Vec::new();
    for entry in fs::read_dir(plugins_dir.path())? {
        let entry = entry?;
        if entry.path().extension() == Some("dll".as_ref()) {
            // Load plugin...
        }
    }
    
    Ok(plugins)
}
```

### 5. **Hybrid Portable/System Integration**

```rust
use app_path::AppPath;
use std::env;

fn get_config_path() -> AppPath {
    // Check for system-wide config first
    if let Ok(system_config) = env::var("MYAPP_SYSTEM_CONFIG") {
        AppPath::new(system_config)  // Absolute path
    } else {
        AppPath::new("config.toml")  // Portable path
    }
}

fn get_data_directory() -> AppPath {
    match env::var("MYAPP_DATA_DIR") {
        Ok(data_dir) => AppPath::new(data_dir),      // System integration
        Err(_) => AppPath::new("data"),              // Portable default
    }
}
```

### 6. **Testing with Temporary Directories**

```rust
use app_path::AppPath;
use std::{env, fs};

#[cfg(test)]
mod tests {
    use super::*;

    fn setup_test_env() -> tempfile::TempDir {
        tempfile::tempdir().unwrap()
    }

    #[test]
    fn test_config_creation() {
        let temp_dir = setup_test_env();
        let config_path = temp_dir.path().join("config.toml");
        let config = AppPath::new(config_path);
        
        // Test config creation logic
        create_default_config(&config);
        assert!(config.exists());
        
        let content = fs::read_to_string(config.path()).unwrap();
        assert!(content.contains("default_value"));
    }
}
```

### 7. **Error Handling Best Practices**

```rust
use app_path::AppPath;
use std::env;

// For applications that need graceful fallbacks
fn get_config_with_fallback() -> AppPath {
    match env::current_exe() {
        Ok(exe_path) => {
            if let Some(exe_dir) = exe_path.parent() {
                let config_path = exe_dir.join("config.toml");
                AppPath::new(config_path)
            } else {
                eprintln!("Warning: Executable at filesystem root, using temp directory");
                let temp_config = env::temp_dir().join("myapp");
                let _ = std::fs::create_dir_all(&temp_config);
                let config_path = temp_config.join("config.toml");
                AppPath::new(config_path)
            }
        }
        Err(_) => {
            eprintln!("Warning: Cannot determine executable location, using temp directory");
            let temp_config = env::temp_dir().join("myapp");
            let _ = std::fs::create_dir_all(&temp_config);
            let config_path = temp_config.join("config.toml");
            AppPath::new(config_path)
        }
    }
}

// For applications that should fail fast
fn get_config_strict() -> AppPath {
    // This will panic with a clear message if executable location fails
    AppPath::new("config.toml")
}
```

### 📋 **Quick Decision Guide**

**Use AppPath when:**
- ✅ You want portable, self-contained applications
- ✅ You need simple, reliable file access relative to your executable
- ✅ You're building CLI tools, portable apps, or development utilities
- ✅ You want to minimize external dependencies

**Consider alternatives when:**
- ❌ You need system-wide configuration (use `directories` crate)
- ❌ You're building system services (use standard system directories)
- ❌ You need complex path manipulation (use `std::path` directly)
- ❌ You require fallible executable location handling

## 📄 License

Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option.

---

**AppPath: Keep it simple, keep it together.** 🎯