hutc 0.1.0

Simple af rest api testing client using lua
use std::{
    fs,
    io::{Error, ErrorKind},
    path::{Path, PathBuf},
};

#[derive(Debug, Clone)]
pub struct LuaSource {
    pub path: PathBuf,
    pub content: String,
}

pub fn load_lua(path: &str) -> Result<Vec<LuaSource>, Error> {
    let root = Path::new(path);
    if !root.exists() {
        return Err(Error::new(
            ErrorKind::NotFound,
            format!("path `{path}` does not exist"),
        ));
    }

    if root.is_file() && !is_lua_file(root) {
        return Err(Error::new(
            ErrorKind::InvalidInput,
            format!(
                "path `{}` is not a Lua file. expected a `.lua` file or a directory containing `.lua` files",
                root.display()
            ),
        ));
    }

    let mut lua_files = Vec::new();
    collect_lua_files(root, &mut lua_files)?;
    lua_files.sort();

    if lua_files.is_empty() {
        return Err(Error::new(
            ErrorKind::NotFound,
            format!("no `.lua` files found under `{}`", root.display()),
        ));
    }

    let mut out = Vec::with_capacity(lua_files.len());
    for file_path in lua_files {
        let content = fs::read_to_string(&file_path).map_err(|e| {
            Error::new(
                e.kind(),
                format!("failed to read Lua file `{}`: {e}", file_path.display()),
            )
        })?;
        out.push(LuaSource {
            path: file_path,
            content,
        });
    }

    Ok(out)
}

fn collect_lua_files(path: &Path, out: &mut Vec<PathBuf>) -> Result<(), Error> {
    if path.is_file() {
        if is_lua_file(path) {
            out.push(path.to_path_buf());
        }
        return Ok(());
    }

    let entries = fs::read_dir(path).map_err(|e| {
        Error::new(
            e.kind(),
            format!("failed to read directory `{}`: {e}", path.display()),
        )
    })?;

    for entry in entries {
        let entry = entry.map_err(|e| {
            Error::new(
                e.kind(),
                format!(
                    "failed to read an entry inside directory `{}`: {e}",
                    path.display()
                ),
            )
        })?;
        let entry_path = entry.path();
        if entry_path.is_dir() {
            collect_lua_files(&entry_path, out)?;
        } else if is_lua_file(&entry_path) {
            out.push(entry_path);
        }
    }

    Ok(())
}

fn is_lua_file(path: &Path) -> bool {
    path.extension().and_then(|s| s.to_str()) == Some("lua")
}