use std::{ fs::{self, DirEntry}, io, path::{Path, PathBuf}, }; pub fn walk_files_recursive( root: impl AsRef, ) -> std::io::Result> { fn visit(dir: &Path, out: &mut Vec) -> std::io::Result<()> { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); let file_type = entry.file_type()?; if file_type.is_dir() { visit(&path, out)?; } else if file_type.is_file() { out.push(entry); } } Ok(()) } let mut files = Vec::new(); visit(root.as_ref(), &mut files)?; Ok(files.into_iter()) } pub fn path_to_lowercase(path: impl AsRef) -> PathBuf { PathBuf::from(path.as_ref().to_string_lossy().to_lowercase()) } pub fn resolve_case_insensitive( base: impl AsRef, rel: impl AsRef, ) -> io::Result> { let mut current = base.as_ref().to_path_buf(); for part in rel.as_ref().iter() { let target = part.to_string_lossy(); let mut found = None; for entry in fs::read_dir(¤t)? { let entry = entry?; let name = entry.file_name(); let name = name.to_string_lossy(); if name.eq_ignore_ascii_case(&target) { found = Some(entry.path()); break; } } match found { Some(path) => current = path, None => { return Ok(None); } } } Ok(Some(current)) }