Traverse archive members lazily through one iterator

This commit is contained in:
Rui Ueyama committed 2026-09-15 00:36:38 +09:00
1 parent 15b984a27c
commit 9bca3eacef
3 files changed
+22 -36

No files matched your search

+20 -26
View File
@@ -166,37 +166,31 @@ fn archive_members(
/// Returns the paths of the members of a thin archive, which are stored
/// outside of the archive file, without opening them.
pub fn get_thin_archive_member_paths(mf: &'static MappedFile) -> impl Iterator<Item = PathBuf> {
archive_members(mf, true).map(move |(name, _)| {
if name.is_absolute() {
name
} else {
mf.name.parent().unwrap_or(Path::new(".")).join(name)
}
})
archive_members(mf, true).map(move |(name, _)| member_path(mf, name))
}
pub fn read_thin_archive_members<'a>(
fn member_path(mf: &MappedFile, name: PathBuf) -> PathBuf {
if name.is_absolute() {
name
} else {
mf.name.parent().unwrap_or(Path::new(".")).join(name)
}
}
/// Opens members as they are consumed. Parallel readers can instead schedule
/// thin-member paths on workers using get_thin_archive_member_paths().
pub fn read_archive_members<'a>(
chroot: &'a Path,
mf: &'static MappedFile,
) -> impl Iterator<Item = &'static MappedFile> + 'a {
get_thin_archive_member_paths(mf).map(move |path| mf.open_thin_member(chroot, &path))
}
pub fn read_fat_archive_members(
mf: &'static MappedFile,
) -> impl Iterator<Item = &'static MappedFile> {
let thin = mf.data().starts_with(b"!<thin>\n");
debug_assert!(thin || mf.data().starts_with(b"!<arch>\n"));
let base = mf.data().as_ptr() as usize;
archive_members(mf, false).map(move |(name, body)| {
let start = body.as_ptr() as usize - base;
mf.slice(name, start, body.len())
archive_members(mf, thin).map(move |(name, body)| {
if thin {
mf.open_thin_member(chroot, &member_path(mf, name))
} else {
mf.slice(name, body.as_ptr() as usize - base, body.len())
}
})
}
pub fn read_archive_members(chroot: &Path, mf: &'static MappedFile) -> Vec<&'static MappedFile> {
if mf.data().starts_with(b"!<arch>\n") {
read_fat_archive_members(mf).collect()
} else {
debug_assert!(mf.data().starts_with(b"!<thin>\n"));
read_thin_archive_members(chroot, mf).collect()
}
}
+1 -9
View File
@@ -287,15 +287,7 @@ pub fn get_machine_type(
) -> Option<&'static str> {
match get_file_type(plugin, mf) {
FileType::ElfObj | FileType::ElfDso | FileType::GccLtoObj => get_elf_target(mf.data()),
FileType::Ar => archive_file::read_fat_archive_members(mf)
.find(|child| {
matches!(
get_file_type(plugin, child),
FileType::ElfObj | FileType::GccLtoObj
)
})
.and_then(|child| get_elf_target(child.data())),
FileType::ThinAr => archive_file::read_thin_archive_members(chroot, mf)
FileType::Ar | FileType::ThinAr => archive_file::read_archive_members(chroot, mf)
.find(|child| {
matches!(
get_file_type(plugin, child),
+1 -1
View File
@@ -359,7 +359,7 @@ pub fn read_input_files<E: Arch>(ctx: &mut Context<E>, jobs: Vec<ReaderJob>) {
// thin archive members, so that file I/O runs in parallel too.
match get_file_type(ctx_ref, mf) {
FileType::Ar => {
for child in archive_file::read_fat_archive_members(mf) {
for child in archive_file::read_archive_members(&ctx_ref.args.chroot, mf) {
let child_rctx = rctx.next_child();
let archive_name = mf.name.as_path();
let loaded = &loaded;