# Walker Module
**Purpose**: Unified file iteration interface abstracting directory walking vs explicit file lists.
## File Responsibilities
### mod.rs
- **Constructors**: from_dir(), from_file_list()
- **Iterator impl**: Delegates to inner walker variant (no overhead)
### dir.rs
- **DirectoryWalker**: Wraps `ignore::WalkBuilder` with per-entry validation
- **Streaming semantics**: Files discovered lazily during iteration
- **Snapshot Isolation**: Uses `ignore` crate's directory snapshot mechanism
- **Syscall Optimization**: Uses cached `entry.metadata()` to avoid redundant `stat` calls
- **Filter chain**: Dotfiles → gitignore → **globs** → patterns → file type
- **Output protection**: Per-entry detection of shell redirection files
### file_list.rs
- **FileListWalker**: Validates and iterates explicit file list
- **Security validation**: Canonicalization, TOCTOU protection, root containment
- **Error filtering**: Invalid files logged to stderr, don't stop iteration
- **Zero-copy iteration**: `IntoIter<PathBuf>` moves values without cloning
## Critical Types
```rust
WalkerEntry {
path: PathBuf, // Absolute, canonical path
relative_path: PathBuf, // Relative to config.root() for display
is_dir: bool,
}
```
## Critical Methods
```rust
Walker::from_dir(config) -> Result<Walker>
// Creates DirectoryWalker with lazy iteration semantics
Walker::from_file_list(files, config) -> Result<Walker>
// Validates each file, filters invalid paths, returns validated iterator
DirectoryWalker::new(config) -> Result<Self>
// Builds WalkBuilder, configures filters, pre-computes stdout identity
// O(1) construction - no filesystem traversal occurs
FileListWalker::validate_file(path, root) -> Result<PathBuf>
// Security: canonicalize, check is_file(), verify within root
```
## Streaming Semantics (DirectoryWalker)
**Design Rationale**: Files are discovered during iteration rather than pre-collected to:
- **Minimize startup latency**: Begin processing immediately
- **Bounded memory**: O(1) peak regardless of directory size
- **Snapshot isolation**: `ignore` crate takes directory snapshot at Walk construction
- **Graceful degradation**: Single file errors don't abort entire walk
**Filter Chain Order:**
1. `ignore` crate filters (dotfiles, .gitignore)
2. **Glob patterns** (user-provided via `--ignore` or config)
3. Directory patterns (e.g., `.git`)
4. File patterns (e.g., extensions)
**Shell Redirection Protection:**
```rust
// Skip files that match stdout inode OR are empty + recently created
// Catches: `luff > output.txt` (shell creates before process starts)
```
## Security (FileListWalker)
```rust
validate_file(path, root) checks:
1. path.exists() && path.metadata().is_file() (fast-path)
2. path.canonicalize() (resolve symlinks to absolute form)
3. canonical.metadata().is_file() (TOCTOU: verify after canonicalize)
4. is_canonical_within_root(canonical, canonical_root) (prevent traversal)
```
## Data Flow
```
Config → Walker construction → Lazy iteration
↓
Iterator yields WalkerItem (Entry | Error)
↓
Printer::print_file() or buffer_entries_with_limit()
```
## Key Invariants
- WalkerEntry.path is always absolute and canonical
- relative_path is always relative to config.root()
- Iterator never panics (errors yielded as WalkerItem::Error)
- DirectoryWalker uses ignore's snapshot isolation for TOCTOU safety
- FileListWalker validates all paths before iteration begins
- FileListWalker yields only files (is_dir is always false)
## Performance Characteristics
- **DirectoryWalker**: O(1) memory, first result available immediately
- **FileListWalker**: O(n) memory for validated path list (n = number of valid files)
- **Enum dispatch**: Zero-cost (compiler optimizes to direct call)
- **No per-entry allocations**: Paths moved, not cloned
- **Syscall Deduplication**: DirectoryWalker reuses metadata from directory entry
## Extension Points
- Parallel walking: Use `ignore::WalkParallel` (requires `Arc<Config>` + channels)
- Progress bars: Use `size_hint()` with `indicatif` crate
- Async I/O: Create async Walker variant with `tokio::fs`
- Custom walkers: Add variant to `Walker` enum, implement `Iterator`