fast-fs 0.2.1

High-speed async file system traversal library with batteries-included file browser component
Documentation
// <FILE>crates/fast-fs/src/nav/fnc_browser_virtual_root.rs</FILE> - <DESC>Synthesize virtual-root entries for multi-root Browser</DESC>
// <VERS>VERSION: 0.1.0</VERS>
// <WCTX>Adding multi-root mounting to Browser</WCTX>
// <CLOG>Initial creation: build synthetic FileEntry list from configured roots</CLOG>

//! Virtual-root entry synthesis
//!
//! When a `Browser` is constructed with multiple roots via `Browser::with_roots`,
//! the top of the navigation tree becomes a synthetic "virtual root" that lists
//! the configured roots as directory entries. This module builds that list.
//!
//! The virtual root is purely synthetic — it has no filesystem backing. Each
//! synthesized entry carries the real path of a root, so entering it behaves
//! exactly like a standard `Browser` rooted at that path.

use crate::FileEntry;
use std::path::{Path, PathBuf};

/// A sentinel path used to mark that the browser is showing the virtual root.
///
/// The value is intentionally implausible as a real filesystem path; callers
/// should check `is_virtual_root_path` rather than matching on the string.
pub const VIRTUAL_ROOT_SENTINEL: &str = "<fast-fs:virtual-root>";

/// Return the sentinel path used to represent the virtual root.
pub fn virtual_root_path() -> PathBuf {
    PathBuf::from(VIRTUAL_ROOT_SENTINEL)
}

/// Returns true if `path` is the virtual-root sentinel.
pub fn is_virtual_root_path(path: &Path) -> bool {
    path.as_os_str() == VIRTUAL_ROOT_SENTINEL
}

/// Build synthetic FileEntry objects for the virtual-root listing.
///
/// Each entry's `path` is the root itself and `name` is a human-readable label
/// derived from the root's final component (falling back to the full path for
/// bare roots like `/`). `is_dir` is always true; hidden/symlink flags are
/// cleared so the virtual root is visible regardless of `show_hidden`.
pub fn build_virtual_root_entries(roots: &[PathBuf]) -> Vec<FileEntry> {
    roots
        .iter()
        .map(|root| {
            let name = root
                .file_name()
                .map(|n| n.to_string_lossy().into_owned())
                .unwrap_or_else(|| root.to_string_lossy().into_owned());
            FileEntry {
                path: root.clone(),
                name,
                is_dir: true,
                is_hidden: false,
                size: 0,
                modified: None,
                is_symlink: false,
                is_readonly: false,
            }
        })
        .collect()
}

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

    #[test]
    fn virtual_root_sentinel_is_detected() {
        assert!(is_virtual_root_path(&virtual_root_path()));
        assert!(!is_virtual_root_path(Path::new("/tmp")));
    }

    #[test]
    fn build_entries_from_named_roots() {
        let roots = vec![PathBuf::from("/tmp/a"), PathBuf::from("/tmp/b")];
        let entries = build_virtual_root_entries(&roots);
        assert_eq!(entries.len(), 2);
        assert_eq!(entries[0].name, "a");
        assert_eq!(entries[1].name, "b");
        assert!(entries.iter().all(|e| e.is_dir));
    }

    #[test]
    fn build_entries_from_bare_root() {
        let roots = vec![PathBuf::from("/")];
        let entries = build_virtual_root_entries(&roots);
        assert_eq!(entries.len(), 1);
        assert!(entries[0].is_dir);
        // name falls back to full path for roots without a file_name
        assert!(!entries[0].name.is_empty());
    }
}

// <FILE>crates/fast-fs/src/nav/fnc_browser_virtual_root.rs</FILE>
// <VERS>END OF VERSION: 0.1.0</VERS>