rust_mir2_core 0.1.5

Shared Rust MIR extraction model and helpers for rust_mir2
Documentation
use std::path::Path;

use anyhow::Context;

use crate::model::{RustMir2Error, TargetMirDump};
use crate::render::sort_target_dumps;

fn sanitize_fragment_part(part: &str) -> String {
    let mut out = String::with_capacity(part.len());
    let mut previous_was_underscore = false;

    for ch in part.chars() {
        let keep = ch.is_ascii_alphanumeric() || ch == '-' || ch == '_';
        if keep {
            out.push(ch);
            previous_was_underscore = false;
        } else if !previous_was_underscore {
            out.push('_');
            previous_was_underscore = true;
        }
    }

    let trimmed = out.trim_matches('_');
    if trimmed.is_empty() {
        "unknown".to_string()
    } else {
        trimmed.to_string()
    }
}

pub fn fragment_file_name(fragment: &TargetMirDump) -> String {
    let package_name = sanitize_fragment_part(&fragment.package_name);
    let target_identity = sanitize_fragment_part(&fragment.target_identity);
    format!("{package_name}__{target_identity}__mir.json")
}

pub fn write_fragment_to_dir(
    output_dir: &Path,
    fragment: &TargetMirDump,
) -> Result<(), RustMir2Error> {
    std::fs::create_dir_all(output_dir)
        .with_context(|| format!("failed to create output dir `{}`", output_dir.display()))?;
    let path = output_dir.join(fragment_file_name(fragment));
    let rendered = serde_json::to_string_pretty(fragment)?;
    std::fs::write(&path, rendered)
        .with_context(|| format!("failed to write fragment `{}`", path.display()))?;
    Ok(())
}

pub fn load_fragments_from_dir(dir: &Path) -> Result<Vec<TargetMirDump>, RustMir2Error> {
    let mut fragments = Vec::new();

    for entry in std::fs::read_dir(dir)
        .with_context(|| format!("failed to read fragment directory `{}`", dir.display()))?
    {
        let entry = entry?;
        let path = entry.path();
        if path.extension().and_then(|value| value.to_str()) != Some("json") {
            continue;
        }

        let content = std::fs::read_to_string(&path)
            .with_context(|| format!("failed to read fragment `{}`", path.display()))?;
        let fragment = serde_json::from_str::<TargetMirDump>(&content)
            .with_context(|| format!("failed to parse fragment `{}`", path.display()))?;
        fragments.push(fragment);
    }

    sort_target_dumps(&mut fragments);
    Ok(fragments)
}