dotscope 0.7.0

A high-performance, cross-platform framework for analyzing and reverse engineering .NET PE executables
Documentation
//! Manifest resource (`.mresource`) directive formatting.
//!
//! Emits ILAsm-compatible `.mresource` directives with visibility,
//! resource name, and source directives for external files or assemblies.

use std::io::{self, Write};

use crate::{
    metadata::{tables::ManifestResourceAttributes, typesystem::CilTypeReference},
    CilObject,
};

/// Write `.mresource` directives for all manifest resources.
///
/// Each resource is emitted with its visibility (`public`/`private`),
/// name, and source directive indicating where the resource data lives:
/// - No source: embedded in the current module
/// - `.file 'name' at 0xOFFSET`: in an external file
/// - `.assembly extern 'name'`: in an external assembly
pub(super) fn format_resources(w: &mut dyn Write, assembly: &CilObject) -> io::Result<()> {
    for entry in assembly.resources().iter() {
        let name = entry.key();
        let resource = entry.value();
        let vis = if resource.flags.contains(ManifestResourceAttributes::PUBLIC) {
            "public"
        } else {
            "private"
        };
        writeln!(w, ".mresource {vis} '{name}' {{")?;

        // Source directive based on implementation
        match &resource.source {
            Some(CilTypeReference::File(file)) => {
                if resource.data_offset > 0 {
                    writeln!(
                        w,
                        "  .file '{}' at 0x{:08X}",
                        file.name, resource.data_offset
                    )?;
                } else {
                    writeln!(w, "  .file '{}'", file.name)?;
                }
            }
            Some(CilTypeReference::AssemblyRef(aref)) => {
                writeln!(w, "  .assembly extern '{}'", aref.name)?;
            }
            _ => {
                // Embedded resource — no source directive needed
            }
        }

        writeln!(w, "}}")?;
    }
    Ok(())
}