Skip to content
Snippets Groups Projects
load.rs 1.28 KiB
Newer Older
Stephen D's avatar
Stephen D committed
use std::{
    fmt::Debug,
    fs,
    path::{Path, PathBuf},
};

use anyhow::Context;

pub trait Loadable: Sized {
    fn load(path: &Path, slug_prefix: &str) -> anyhow::Result<Self>;
}

pub fn load_from_path<L: Loadable>(path: &str, slug_prefix: &str) -> anyhow::Result<Vec<L>> {
    recursive_scan(path)?
        .iter()
        .map(|file_path| {
            let mut diff: PathBuf = file_path.strip_prefix(path)?.into();
            diff.pop();
            let diff = diff
                .to_str()
                .context("Could not convert path to a string")?;

            let prefix = if diff.is_empty() {
                slug_prefix.to_string()
            } else if slug_prefix.is_empty() {
                diff.to_string()
            } else {
                format!("{slug_prefix}/{diff}")
            };
            L::load(file_path, &prefix)
        })
        .collect()
}

pub fn recursive_scan<P>(path: P) -> anyhow::Result<Vec<PathBuf>>
where
    P: AsRef<Path> + Debug,
{
    let mut out = vec![];

    for entry in fs::read_dir(path)? {
        let entry = entry?;
        let t = entry.file_type()?;
        let path = entry.path();

        if t.is_dir() {
            out.extend(recursive_scan(&path)?);
        } else {
            out.push(path);
        }
    }

    Ok(out)
}