mumu-test 0.1.2

Test suite plugin for the Lava language
Documentation
// test/src/lorem_file.rs

use mumu::{
    parser::interpreter::Interpreter,
    parser::types::{FunctionValue, Value},
};

use std::{
    sync::{Arc, Mutex},
    fs::{self, File},
    io::Write,
    path::Path,
};

use sha2::{Sha256, Digest}; // for hashing

/// A helper that generates classical Lorem Ipsum text up to `n` characters.
/// If `n` exceeds our base text length, we can repeat, or just keep it simple for demonstration.
fn generate_lorem_ipsum(n: usize) -> String {
    let base = "\
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do \
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad \
minim veniam, quis nostrud exercitation ullamco laboris nisi ut \
aliquip ex ea commodo consequat. Duis aute irure dolor in \
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in \
culpa qui officia deserunt mollit anim id est laborum. ";

    let mut out = String::new();
    while out.len() < n {
        out.push_str(base);
    }
    out.truncate(n);
    out
}

/// The bridging function: test:lorem_file(int).
/// - Generate n chars of Lorem text.
/// - Compute SHA-256 -> first 2 bytes => 4 hex chars => short hash.
/// - Ensure a `tmp` folder in the project root.
/// - Write the file => `tmp/lorem_XXXX`.
/// - Return the path as SingleString.
fn lorem_file_bridge_fn(_interp: &mut Interpreter, mut args: Vec<Value>) -> Result<Value, String> {
    if args.len() != 1 {
        return Err(format!("lorem_file => expected 1 integer arg => got {}", args.len()));
    }

    let n_val = args.remove(0);
    let n = match n_val {
        Value::Int(i) if i > 0 => i as usize,
        Value::IntArray(ref arr) if arr.len() == 1 && arr[0] > 0 => arr[0] as usize,
        _ => return Err(format!("lorem_file => argument must be a positive integer, got {:?}", n_val)),
    };

    // 1) Generate text
    let text = generate_lorem_ipsum(n);

    // 2) Hash => first 2 bytes => 4 hex chars
    let mut hasher = Sha256::new();
    hasher.update(text.as_bytes());
    let digest = hasher.finalize();
    let full_hex = hex::encode(digest); // 64 hex chars total
    let short_hex = &full_hex[..4]; // first 4 => 2 bytes

    // 3) Ensure `./tmp` subdir in project root
    let tmp_path = Path::new("tmp");
    if !tmp_path.exists() {
        fs::create_dir_all(tmp_path)
            .map_err(|e| format!("lorem_file => cannot create tmp folder: {}", e))?;
    }

    // 4) Construct final name => tmp/lorem_<short_hex>
    let file_name = format!("lorem_{}", short_hex);
    let file_path = tmp_path.join(file_name);

    // 5) Write the file
    let mut f = File::create(&file_path)
        .map_err(|e| format!("lorem_file => failed creating '{:?}': {}", file_path, e))?;
    f.write_all(text.as_bytes())
        .map_err(|e| format!("lorem_file => failed writing => {}", e))?;

    // 6) Return the final path as SingleString
    let path_str = file_path.to_string_lossy().to_string();
    Ok(Value::SingleString(path_str))
}

/// A helper function to register the bridging => `test:lorem_file`.
pub fn register_lorem_file(interp: &mut Interpreter) {
    let fn_arc = Arc::new(Mutex::new(lorem_file_bridge_fn));
    interp.register_dynamic_function("test:lorem_file", fn_arc);
    interp.set_variable(
        "test:lorem_file",
        Value::Function(Box::new(FunctionValue::Named("test:lorem_file".to_string())))
    );
}