dirwalk 1.1.1

Platform-optimized recursive directory walker with metadata
Documentation
//! On-demand tree reconstruction from flat walk results.
//!
//! [`to_tree`] converts a flat `&[Entry]` into a `Vec<TreeEntry>` hierarchy
//! using `relative_path` and `depth`.

use crate::entry::Entry;
use crate::util::parent_dir;
use std::collections::HashMap;

pub struct TreeEntry {
    pub entry: Entry,
    pub children: Vec<TreeEntry>,
}

/// Build a tree from a flat sorted list of entries.
/// Entries must have correct `relative_path` and `depth`.
/// Accepts `&[Entry]` or `&[&Entry]`.
pub fn to_tree<E: AsRef<Entry>>(entries: &[E]) -> Vec<TreeEntry> {
    let mut children_map: HashMap<String, Vec<Entry>> = HashMap::new();

    for entry in entries {
        let entry = entry.as_ref();
        let parent = parent_dir(&entry.relative_path).to_owned();
        children_map.entry(parent).or_default().push(entry.clone());
    }

    build_subtree("", &mut children_map)
}

fn build_subtree(parent: &str, children_map: &mut HashMap<String, Vec<Entry>>) -> Vec<TreeEntry> {
    let Some(children) = children_map.remove(parent) else {
        return Vec::new();
    };

    children
        .into_iter()
        .map(|entry| {
            let subtree = if entry.is_dir {
                build_subtree(&entry.relative_path, children_map)
            } else {
                Vec::new()
            };
            TreeEntry {
                entry,
                children: subtree,
            }
        })
        .collect()
}