use std::borrow::Cow;
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::{self, BufWriter, Write};
use std::path::{Path, PathBuf};

use ar_archive_writer::{
    ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, write_archive_to_stream,
};
pub use ar_archive_writer::{DEFAULT_OBJECT_READER, ObjectReader};
use object::read::archive::{ArchiveFile, ArchiveKind as ObjectArchiveKind};
use object::read::macho::FatArch;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_fs_util::TempDirBuilder;
use rustc_metadata::EncodedMetadata;
use rustc_session::Session;
use rustc_span::Symbol;
use rustc_target::spec::Arch;
use tracing::trace;

use super::metadata::{create_compressed_metadata_file, search_for_section};
use super::rmeta_link::{self, RmetaLinkCache};
use super::symbol_edit::{apply_edits, collect_internal_names};
use crate::common;
// Public for ArchiveBuilderBuilder::extract_bundled_libs
pub use crate::diagnostics::ExtractBundledLibsError;
use crate::diagnostics::{
    ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
    ErrorWritingDEFFile, UnknownArchiveKind,
};

/// An item to be included in an import library.
/// This is a slimmed down version of `COFFShortExport` from `ar-archive-writer`.
pub struct ImportLibraryItem {
    /// The name to be exported.
    pub name: String,
    /// The ordinal to be exported, if any.
    pub ordinal: Option<u16>,
    /// The original, decorated name if `name` is not decorated.
    pub symbol_name: Option<String>,
    /// True if this is a data export, false if it is a function export.
    pub is_data: bool,
}

impl ImportLibraryItem {
    fn into_coff_short_export(self, sess: &Session) -> COFFShortExport {
        let import_name = (sess.target.arch == Arch::Arm64EC).then(|| self.name.clone());
        COFFShortExport {
            name: self.name,
            ext_name: None,
            symbol_name: self.symbol_name,
            import_name,
            export_as: None,
            ordinal: self.ordinal.unwrap_or(0),
            noname: self.ordinal.is_some(),
            data: self.is_data,
            private: false,
            constant: false,
        }
    }
}

pub trait ArchiveBuilderBuilder {
    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;

    fn create_dylib_metadata_wrapper(
        &self,
        sess: &Session,
        metadata: &EncodedMetadata,
        symbol_name: &str,
    ) -> Vec<u8> {
        create_compressed_metadata_file(sess, metadata, symbol_name)
    }

    /// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
    /// and returns the path on disk to that import library.
    /// This functions doesn't take `self` so that it can be called from
    /// `linker_with_args`, which is specialized on `ArchiveBuilder` but
    /// doesn't take or create an instance of that type.
    fn create_dll_import_lib(
        &self,
        sess: &Session,
        lib_name: &str,
        items: Vec<ImportLibraryItem>,
        output_path: &Path,
    ) {
        if common::is_mingw_gnu_toolchain(&sess.target) {
            // The binutils linker used on -windows-gnu targets cannot read the import
            // libraries generated by LLVM: in our attempts, the linker produced an .EXE
            // that loaded but crashed with an AV upon calling one of the imported
            // functions. Therefore, use binutils to create the import library instead,
            // by writing a .DEF file to the temp dir and calling binutils's dlltool.
            create_mingw_dll_import_lib(sess, lib_name, items, output_path);
        } else {
            trace!("creating import library");
            trace!("  dll_name {:#?}", lib_name);
            trace!("  output_path {}", output_path.display());
            trace!(
                "  import names: {}",
                items
                    .iter()
                    .map(|ImportLibraryItem { name, .. }| name.clone())
                    .collect::<Vec<_>>()
                    .join(", "),
            );

            // All import names are Rust identifiers and therefore cannot contain \0 characters.
            // FIXME: when support for #[link_name] is implemented, ensure that the import names
            // still don't contain any \0 characters. Also need to check that the names don't
            // contain substrings like " @" or "NONAME" that are keywords or otherwise reserved
            // in definition files.

            let mut file = match fs::File::create_new(&output_path) {
                Ok(file) => file,
                Err(error) => sess
                    .dcx()
                    .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
            };

            let exports =
                items.into_iter().map(|item| item.into_coff_short_export(sess)).collect::<Vec<_>>();
            let machine = match &sess.target.arch {
                Arch::X86_64 => MachineTypes::AMD64,
                Arch::X86 => MachineTypes::I386,
                Arch::AArch64 => MachineTypes::ARM64,
                Arch::Arm64EC => MachineTypes::ARM64EC,
                Arch::Arm => MachineTypes::ARMNT,
                cpu => panic!("unsupported cpu type {cpu}"),
            };

            if let Err(error) = ar_archive_writer::write_import_library(
                &mut file,
                lib_name,
                &exports,
                machine,
                !sess.target.is_like_msvc,
                // Enable compatibility with MSVC's `/WHOLEARCHIVE` flag.
                // Without this flag a duplicate symbol error would be emitted
                // when linking a rust staticlib using `/WHOLEARCHIVE`.
                // See #129020
                true,
                &[],
            ) {
                sess.dcx()
                    .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
            }
        }
    }

    fn extract_bundled_libs<'a>(
        &'a self,
        rlib: &'a Path,
        outdir: &Path,
        bundled_lib_file_names: &FxIndexSet<Symbol>,
    ) -> Result<(), ExtractBundledLibsError<'a>> {
        let archive_map = unsafe {
            Mmap::map(
                File::open(rlib)
                    .map_err(|e| ExtractBundledLibsError::OpenFile { rlib, error: Box::new(e) })?,
            )
            .map_err(|e| ExtractBundledLibsError::MmapFile { rlib, error: Box::new(e) })?
        };
        let archive = ArchiveFile::parse(&*archive_map)
            .map_err(|e| ExtractBundledLibsError::ParseArchive { rlib, error: Box::new(e) })?;

        for entry in archive.members() {
            let entry = entry
                .map_err(|e| ExtractBundledLibsError::ReadEntry { rlib, error: Box::new(e) })?;
            let data = entry
                .data(&*archive_map)
                .map_err(|e| ExtractBundledLibsError::ArchiveMember { rlib, error: Box::new(e) })?;
            let name = std::str::from_utf8(entry.name())
                .map_err(|e| ExtractBundledLibsError::ConvertName { rlib, error: Box::new(e) })?;
            if !bundled_lib_file_names.contains(&Symbol::intern(name)) {
                continue; // We need to extract only native libraries.
            }
            let data = search_for_section(rlib, data, ".bundled_lib").map_err(|e| {
                ExtractBundledLibsError::ExtractSection { rlib, error: Box::<dyn Error>::from(e) }
            })?;
            std::fs::write(&outdir.join(&name), data)
                .map_err(|e| ExtractBundledLibsError::WriteFile { rlib, error: Box::new(e) })?;
        }
        Ok(())
    }
}

fn create_mingw_dll_import_lib(
    sess: &Session,
    lib_name: &str,
    items: Vec<ImportLibraryItem>,
    output_path: &Path,
) {
    let def_file_path = output_path.with_extension("def");

    let def_file_content = format!(
        "EXPORTS\n{}",
        items
            .into_iter()
            .map(|ImportLibraryItem { name, ordinal, .. }| {
                match ordinal {
                    Some(n) => format!("{name} @{n} NONAME"),
                    None => name,
                }
            })
            .collect::<Vec<String>>()
            .join("\n")
    );

    match std::fs::write(&def_file_path, def_file_content) {
        Ok(_) => {}
        Err(e) => {
            sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
        }
    };

    // --no-leading-underscore: For the `import_name_type` feature to work, we need to be
    // able to control the *exact* spelling of each of the symbols that are being imported:
    // hence we don't want `dlltool` adding leading underscores automatically.
    let dlltool = find_binutils_dlltool(sess);
    // temp_prefix doesn't handle paths with spaces so
    // use a relative path and set the current working directory
    let cwd = output_path.parent().unwrap_or(output_path);
    let temp_prefix = lib_name;
    // dlltool target architecture args from:
    // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
    let (dlltool_target_arch, dlltool_target_bitness) = match &sess.target.arch {
        Arch::X86_64 => ("i386:x86-64", "--64"),
        Arch::X86 => ("i386", "--32"),
        Arch::AArch64 => ("arm64", "--64"),
        Arch::Arm => ("arm", "--32"),
        arch => panic!("unsupported arch {arch}"),
    };
    let mut dlltool_cmd = std::process::Command::new(&dlltool);
    dlltool_cmd
        .arg("-d")
        .arg(def_file_path)
        .arg("-D")
        .arg(lib_name)
        .arg("-l")
        .arg(&output_path)
        .arg("-m")
        .arg(dlltool_target_arch)
        .arg("-f")
        .arg(dlltool_target_bitness)
        .arg("--no-leading-underscore")
        .arg("--temp-prefix")
        .arg(temp_prefix)
        .current_dir(cwd);

    match dlltool_cmd.output() {
        Err(e) => {
            sess.dcx().emit_fatal(ErrorCallingDllTool {
                dlltool_path: dlltool.to_string_lossy(),
                error: e,
            });
        }
        // dlltool returns '0' on failure, so check for error output instead.
        Ok(output) if !output.stderr.is_empty() => {
            sess.dcx().emit_fatal(DlltoolFailImportLibrary {
                dlltool_path: dlltool.to_string_lossy(),
                dlltool_args: dlltool_cmd
                    .get_args()
                    .map(|arg| arg.to_string_lossy())
                    .collect::<Vec<_>>()
                    .join(" "),
                stdout: String::from_utf8_lossy(&output.stdout),
                stderr: String::from_utf8_lossy(&output.stderr),
            })
        }
        _ => {}
    }
}

fn find_binutils_dlltool(sess: &Session) -> OsString {
    assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
    if let Some(dlltool_path) = &sess.opts.cg.dlltool {
        return dlltool_path.clone().into_os_string();
    }

    let tool_name: OsString = if sess.host.options.is_like_windows {
        // If we're compiling on Windows, always use "dlltool.exe".
        "dlltool.exe"
    } else {
        // On other platforms, use the architecture-specific name.
        match sess.target.arch {
            Arch::X86_64 => "x86_64-w64-mingw32-dlltool",
            Arch::X86 => "i686-w64-mingw32-dlltool",
            Arch::AArch64 => "aarch64-w64-mingw32-dlltool",

            // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
            _ => "dlltool",
        }
    }
    .into();

    // NOTE: it's not clear how useful it is to explicitly search PATH.
    for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
        let full_path = dir.join(&tool_name);
        if full_path.is_file() {
            return full_path.into_os_string();
        }
    }

    // The user didn't specify the location of the dlltool binary, and we weren't able
    // to find the appropriate one on the PATH. Just return the name of the tool
    // and let the invocation fail with a hopefully useful error message.
    tool_name
}

pub enum AddArchiveKind<'a> {
    Rlib(&'a mut RmetaLinkCache, /*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool),
    Other,
}

pub struct ArchiveSymbols {
    pub exported: FxHashSet<String>,
    pub rename_suffix: Option<String>,
    pub hide: bool,
}

pub trait ArchiveBuilder {
    fn add_file(&mut self, path: &Path, kind: ArchiveEntryKind);

    fn add_archive(&mut self, archive: &Path, kind: AddArchiveKind<'_>) -> io::Result<()>;

    fn build(self: Box<Self>, output: &Path, symbols: Option<ArchiveSymbols>) -> bool;
}

fn target_archive_format_to_object_kind(format: &str) -> Option<ObjectArchiveKind> {
    match format {
        "gnu" => Some(ObjectArchiveKind::Gnu),
        "bsd" => Some(ObjectArchiveKind::Bsd),
        "darwin" => Some(ObjectArchiveKind::Bsd64),
        "coff" => Some(ObjectArchiveKind::Coff),
        "aix_big" => Some(ObjectArchiveKind::AixBig),
        _ => None,
    }
}

fn archive_kinds_compatible(actual: ObjectArchiveKind, expected: ObjectArchiveKind) -> bool {
    if actual == expected {
        return true;
    }
    matches!(
        (actual, expected),
        // An archive without long filenames or symbol table is detected as Unknown;
        // this is compatible with any target format.
        (ObjectArchiveKind::Unknown, _)
        // 64-bit symbol table variants are compatible with their 32-bit counterparts
        | (ObjectArchiveKind::Gnu64, ObjectArchiveKind::Gnu)
        | (ObjectArchiveKind::Gnu, ObjectArchiveKind::Gnu64)
        | (ObjectArchiveKind::Bsd64, ObjectArchiveKind::Bsd)
        | (ObjectArchiveKind::Bsd, ObjectArchiveKind::Bsd64)
        // GNU and COFF archives share the same magic and member header format;
        // only the symbol table layout differs.
        | (ObjectArchiveKind::Gnu, ObjectArchiveKind::Coff)
        | (ObjectArchiveKind::Coff, ObjectArchiveKind::Gnu)
        | (ObjectArchiveKind::Gnu64, ObjectArchiveKind::Coff)
    )
}

fn archive_kind_display_name(kind: ObjectArchiveKind) -> String {
    match kind {
        ObjectArchiveKind::Gnu | ObjectArchiveKind::Gnu64 => "GNU".to_string(),
        ObjectArchiveKind::Bsd => "BSD".to_string(),
        ObjectArchiveKind::Bsd64 => "Darwin".to_string(),
        ObjectArchiveKind::Coff => "COFF".to_string(),
        ObjectArchiveKind::AixBig => "AIX big".to_string(),
        _ => format!("{kind:?}"),
    }
}

pub struct ArArchiveBuilderBuilder;

impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
    fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
        Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
    }
}

#[must_use = "must call build() to finish building the archive"]
pub struct ArArchiveBuilder<'a> {
    sess: &'a Session,
    object_reader: &'static ObjectReader,

    src_archives: Vec<(PathBuf, Mmap)>,
    // Don't use an `HashMap` here, as the order is important. `lib.rmeta` needs
    // to be at the end of an archive in some cases for linkers to not get confused.
    entries: Vec<(Vec<u8>, ArchiveEntry)>,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ArchiveEntryKind {
    /// Object file produced from Rust code.
    RustObj,
    /// Anything else, introduce new variants as needed.
    Other,
}

#[derive(Debug)]
enum ArchiveEntrySource {
    Archive { archive_index: usize, file_range: (u64, u64) },
    File(PathBuf),
}

#[derive(Debug)]
struct ArchiveEntry {
    source: ArchiveEntrySource,
    kind: ArchiveEntryKind,
}

impl<'a> ArArchiveBuilder<'a> {
    pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchiveBuilder<'a> {
        ArArchiveBuilder { sess, object_reader, src_archives: vec![], entries: vec![] }
    }
}

fn try_filter_fat_archs(
    archs: &[impl FatArch],
    target_arch: object::Architecture,
    archive_path: &Path,
    archive_map_data: &[u8],
) -> io::Result<Option<PathBuf>> {
    let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
        Some(a) => a,
        None => return Ok(None),
    };

    let (mut new_f, extracted_path) = tempfile::Builder::new()
        .suffix(archive_path.file_name().unwrap())
        .tempfile()?
        .keep()
        .unwrap();

    new_f.write_all(
        desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
    )?;

    Ok(Some(extracted_path))
}

pub fn try_extract_macho_fat_archive(
    sess: &Session,
    archive_path: &Path,
) -> io::Result<Option<PathBuf>> {
    let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
    let target_arch = match sess.target.arch {
        Arch::AArch64 => object::Architecture::Aarch64,
        Arch::X86_64 => object::Architecture::X86_64,
        _ => return Ok(None),
    };

    if let Ok(h) = object::read::macho::MachOFatFile32::parse(&*archive_map) {
        let archs = h.arches();
        try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
    } else if let Ok(h) = object::read::macho::MachOFatFile64::parse(&*archive_map) {
        let archs = h.arches();
        try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
    } else {
        // Not a FatHeader at all, just return None.
        Ok(None)
    }
}

impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
    fn add_archive(
        &mut self,
        archive_path: &Path,
        mut ar_kind: AddArchiveKind<'_>,
    ) -> io::Result<()> {
        let mut archive_path = archive_path.to_path_buf();
        if self.sess.target.llvm_target.contains("-apple-macosx")
            && let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)?
        {
            archive_path = new_archive_path
        }

        if self.src_archives.iter().any(|archive| archive.0 == archive_path) {
            return Ok(());
        }

        let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? };
        let archive = ArchiveFile::parse(&*archive_map)
            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
        let skip = match &ar_kind {
            AddArchiveKind::Rlib(_, skip) => Some(*skip),
            AddArchiveKind::Other => None,
        };
        let metadata_link = match &mut ar_kind {
            AddArchiveKind::Rlib(cache, _) => cache.get_or_insert_with(&archive_path, || {
                rmeta_link::read(&archive, &archive_map, &archive_path)
            }),
            AddArchiveKind::Other => None,
        };
        let archive_index = self.src_archives.len();

        if let Some(expected_kind) =
            target_archive_format_to_object_kind(&self.sess.target.archive_format)
        {
            let actual_kind = archive.kind();
            if !archive_kinds_compatible(actual_kind, expected_kind) {
                self.sess.dcx().emit_warn(crate::diagnostics::IncompatibleArchiveFormat {
                    path: archive_path.clone(),
                    actual: archive_kind_display_name(actual_kind),
                    expected: archive_kind_display_name(expected_kind),
                });
            }
        }

        for entry in archive.members() {
            let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
            let file_name = String::from_utf8(entry.name().to_vec())
                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
            let kind = if metadata_link
                .as_ref()
                .is_some_and(|m| m.rust_object_files.iter().any(|f| f == &file_name))
            {
                ArchiveEntryKind::RustObj
            } else {
                ArchiveEntryKind::Other
            };
            let drop = match skip {
                Some(skip) => skip(&file_name, kind),
                None => false,
            };
            if !drop {
                let source = if entry.is_thin() {
                    let member_path = archive_path.parent().unwrap().join(Path::new(&file_name));
                    ArchiveEntrySource::File(member_path)
                } else {
                    ArchiveEntrySource::Archive { archive_index, file_range: entry.file_range() }
                };
                self.entries.push((file_name.into_bytes(), ArchiveEntry { source, kind }));
            }
        }

        self.src_archives.push((archive_path, archive_map));
        Ok(())
    }

    /// Adds an arbitrary file to this archive
    fn add_file(&mut self, file: &Path, kind: ArchiveEntryKind) {
        self.entries.push((
            file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(),
            ArchiveEntry { source: ArchiveEntrySource::File(file.to_owned()), kind },
        ));
    }

    /// Combine the provided files, rlibs, and native libraries into a single
    /// `Archive`.
    fn build(self: Box<Self>, output: &Path, symbols: Option<ArchiveSymbols>) -> bool {
        let sess = self.sess;
        match self.build_inner(output, symbols) {
            Ok(any_members) => any_members,
            Err(error) => {
                sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
            }
        }
    }
}

impl<'a> ArArchiveBuilder<'a> {
    fn build_inner(self, output: &Path, symbols: Option<ArchiveSymbols>) -> io::Result<bool> {
        let archive_kind = match &*self.sess.target.archive_format {
            "gnu" => ArchiveKind::Gnu,
            "bsd" => ArchiveKind::Bsd,
            "darwin" => ArchiveKind::Darwin,
            "coff" => ArchiveKind::Coff,
            "aix_big" => ArchiveKind::AixBig,
            kind => {
                self.sess.dcx().emit_fatal(UnknownArchiveKind { kind });
            }
        };

        // Collect all internally-defined symbol names across every Rust object file.
        // This set is needed because rename must also apply to *undefined* references
        // (cross-object calls within the staticlib), but we cannot use `!exported.contains(name)`
        // alone — that would also match external C symbols like `malloc` which must not be renamed.
        let rename = if let Some(sym) = &symbols
            && let Some(rename_suffix) = sym.rename_suffix.as_deref()
        {
            let mut names = FxHashSet::default();
            for (_, entry) in &self.entries {
                if entry.kind != ArchiveEntryKind::RustObj {
                    continue;
                }
                match &entry.source {
                    ArchiveEntrySource::Archive { archive_index, file_range } => {
                        let src_archive = &self.src_archives[*archive_index];
                        let start = file_range.0 as usize;
                        let end = start + file_range.1 as usize;
                        if let Some(data) = src_archive.1.get(start..end) {
                            collect_internal_names(data, &sym.exported, &mut names);
                        }
                    }
                    ArchiveEntrySource::File(file) => {
                        if let Ok(data) = fs::read(file) {
                            collect_internal_names(&data, &sym.exported, &mut names);
                        }
                    }
                }
            }
            Some((names, rename_suffix))
        } else {
            None
        };

        let mut entries = Vec::new();

        for (entry_name, entry) in self.entries {
            let data: Box<dyn AsRef<[u8]>> = match entry.source {
                ArchiveEntrySource::Archive { archive_index, file_range } => {
                    let src_archive = &self.src_archives[archive_index];
                    let archive_data = &src_archive.1;
                    let start = file_range.0 as usize;
                    let end = start + file_range.1 as usize;
                    let Some(data) = archive_data.get(start..end) else {
                        return Err(io_error_context(
                            "invalid archive member",
                            io::Error::new(
                                io::ErrorKind::InvalidData,
                                format!(
                                    "archive member of {} at offset {start} with size {} \
                                         exceeds archive size {} in `{}`",
                                    src_archive.0.display(),
                                    file_range.1,
                                    archive_data.len(),
                                    src_archive.0.display(),
                                ),
                            ),
                        ));
                    };

                    if entry.kind == ArchiveEntryKind::RustObj
                        && let Some(sym) = &symbols
                    {
                        Box::new(apply_edits(data, &sym.exported, sym.hide, rename.as_ref()))
                    } else {
                        Box::new(data)
                    }
                }
                ArchiveEntrySource::File(file) => unsafe {
                    let mmap = Mmap::map(File::open(&file).map_err(|err| {
                        io_error_context(
                            &format!("failed to open object file {}", file.display()),
                            err,
                        )
                    })?)
                    .map_err(|err| {
                        io_error_context(
                            &format!("failed to map object file {}", file.display()),
                            err,
                        )
                    })?;
                    if entry.kind == ArchiveEntryKind::RustObj
                        && let Some(sym) = &symbols
                    {
                        let edited = apply_edits(&mmap, &sym.exported, sym.hide, rename.as_ref());
                        match edited {
                            Cow::Borrowed(_) => Box::new(mmap) as Box<dyn AsRef<[u8]>>,
                            Cow::Owned(v) => Box::new(v),
                        }
                    } else {
                        Box::new(mmap) as Box<dyn AsRef<[u8]>>
                    }
                },
            };

            entries.push(NewArchiveMember {
                buf: data,
                object_reader: self.object_reader,
                member_name: String::from_utf8(entry_name).unwrap(),
                mtime: 0,
                uid: 0,
                gid: 0,
                perms: 0o644,
            })
        }

        // Write to a temporary file first before atomically renaming to the final name.
        // This prevents programs (including rustc) from attempting to read a partial archive.
        // It also enables writing an archive with the same filename as a dependency on Windows as
        // required by a test.
        // The tempfile crate currently uses 0o600 as mode for the temporary files and directories
        // it creates. We need it to be the default mode for back compat reasons however. (See
        // #107495) To handle this we are telling tempfile to create a temporary directory instead
        // and then inside this directory create a file using File::create.
        let archive_tmpdir = TempDirBuilder::new()
            .suffix(".temp-archive")
            .tempdir_in(output.parent().unwrap_or_else(|| Path::new("")))
            .map_err(|err| {
                io_error_context("couldn't create a directory for the temp file", err)
            })?;
        let archive_tmpfile_path = archive_tmpdir.path().join("tmp.a");
        let archive_tmpfile = File::create_new(&archive_tmpfile_path)
            .map_err(|err| io_error_context("couldn't create the temp file", err))?;

        let mut archive_tmpfile = BufWriter::new(archive_tmpfile);
        write_archive_to_stream(
            &mut archive_tmpfile,
            &entries,
            archive_kind,
            false,
            /* is_ec = */ Some(self.sess.target.arch == Arch::Arm64EC),
        )?;
        archive_tmpfile.flush()?;
        drop(archive_tmpfile);

        let any_entries = !entries.is_empty();
        drop(entries);
        // Drop src_archives to unmap all input archives, which is necessary if we want to write the
        // output archive to the same location as an input archive on Windows.
        drop(self.src_archives);

        fs::rename(archive_tmpfile_path, output)
            .map_err(|err| io_error_context("failed to rename archive file", err))?;
        archive_tmpdir
            .close()
            .map_err(|err| io_error_context("failed to remove temporary directory", err))?;

        Ok(any_entries)
    }
}

fn io_error_context(context: &str, err: io::Error) -> io::Error {
    io::Error::new(io::ErrorKind::Other, format!("{context}: {err}"))
}
