rust_mir2_core 0.1.4

Shared Rust MIR extraction model and helpers for rust_mir2
Documentation
use std::collections::BTreeMap;
use std::fmt::Write as _;
use std::path::{Path, PathBuf};

use crate::model::{PackageMirDump, RustMir2Error, TargetMirDump, WorkspaceMirDump};

pub fn render_workspace_mir_json(
    dump: &WorkspaceMirDump,
    pretty: bool,
) -> Result<String, RustMir2Error> {
    let mut sorted = dump.clone();
    sort_workspace_dump(&mut sorted);

    let rendered = if pretty {
        serde_json::to_string_pretty(&sorted)
    } else {
        serde_json::to_string(&sorted)
    }?;

    Ok(rendered)
}

pub fn default_output_path_for_cwd(cwd: &Path) -> PathBuf {
    cwd.join("rust_mir2.json")
}

pub fn default_mir_output_dir_for_cwd(cwd: &Path) -> PathBuf {
    cwd.join("rust_mir2_emit_mir")
}

pub(crate) fn sort_target_dumps(targets: &mut [TargetMirDump]) {
    targets.sort_by(|left, right| {
        (
            &left.package_name,
            &left.target_identity,
            &left.target_kind,
            &left.target_name,
            &left.target_src_path,
        )
            .cmp(&(
                &right.package_name,
                &right.target_identity,
                &right.target_kind,
                &right.target_name,
                &right.target_src_path,
            ))
    });
}

fn sort_packages(packages: &mut [PackageMirDump]) {
    packages.sort_by(|left, right| left.package_name.cmp(&right.package_name));
    for package in packages {
        sort_target_dumps(&mut package.targets);
    }
}

fn sort_workspace_dump(dump: &mut WorkspaceMirDump) {
    sort_packages(&mut dump.packages);
}

pub(crate) fn build_packages_from_targets(targets: Vec<TargetMirDump>) -> Vec<PackageMirDump> {
    let mut grouped = BTreeMap::<String, Vec<TargetMirDump>>::new();
    for target in targets {
        grouped
            .entry(target.package_name.clone())
            .or_default()
            .push(target);
    }

    let mut packages = grouped
        .into_iter()
        .map(|(package_name, mut targets)| {
            sort_target_dumps(&mut targets);
            let merged_mir_raw = merge_target_mir(&targets);
            PackageMirDump {
                package_name,
                targets,
                merged_mir_raw,
            }
        })
        .collect::<Vec<_>>();

    sort_packages(&mut packages);
    packages
}

fn merge_target_mir(targets: &[TargetMirDump]) -> String {
    let mut out = String::new();

    for target in targets {
        let content = target.mir_raw.trim();
        if content.is_empty() {
            continue;
        }

        if !out.is_empty() {
            out.push_str("\n\n");
        }

        let _ = writeln!(&mut out, "=== TARGET {} / mir ===", target.target_identity);
        let _ = writeln!(&mut out, "package_name: {}", target.package_name);
        let _ = writeln!(&mut out, "crate_name: {}", target.crate_name);
        let _ = writeln!(&mut out, "target_name: {}", target.target_name);
        let _ = writeln!(&mut out, "target_kind: {}", target.target_kind);
        let _ = writeln!(&mut out, "target_profile: {}", target.target_profile);
        let _ = writeln!(
            &mut out,
            "target_src_path: {}",
            target.target_src_path.display()
        );
        let _ = writeln!(&mut out);
        out.push_str(content);
    }

    out
}