add Apk::merge

This commit is contained in:
Jean-Marie Mineau 2025-03-26 17:04:19 +01:00
parent 6e218f85f9
commit 64a4804371
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2

View file

@ -3307,4 +3307,64 @@ impl Apk {
})) }))
} }
} }
/// Merget two application into one.
pub fn merge(&mut self, Self { mut dex_files }: Self) -> Result<()> {
let mut i = 0;
let mut name: String = "classes.dex".into();
while self.dex_files.contains_key(&name) {
i += 1;
name = format!("classes{}.dex", i + 1);
}
let mut j = 0;
let mut other_name: String = "classes.dex".into();
while let Some(file) = dex_files.remove(&other_name) {
self.dex_files.insert(name.clone(), file);
j += 1;
other_name = format!("classes{}.dex", j + 1);
while self.dex_files.contains_key(&name) {
i += 1;
name = format!("classes{}.dex", i + 1);
}
}
// Maybe not a good idea reinserting invalid .dex as valid ones, so explicitly skip one
// index to keep the files invalids.
i += 1;
name = format!("classes{}.dex", i + 1);
while self.dex_files.contains_key(&name) {
i += 1;
name = format!("classes{}.dex", i + 1);
}
for (other_name, dex) in dex_files.into_iter() {
if get_dex_name_index(&other_name).is_some() {
self.dex_files.insert(name.clone(), dex);
while self.dex_files.contains_key(&name) {
i += 1;
name = format!("classes{}.dex", i + 1);
}
} else {
let mut new_name = other_name.clone();
let mut k = 1;
while self.dex_files.contains_key(&new_name) {
k += 1;
new_name = format!("{other_name}-{k}")
}
self.dex_files.insert(new_name, dex);
}
}
Ok(())
}
}
/// Parse a .dex file name, and if it is a valid android file, return the index of the file.
fn get_dex_name_index(name: &str) -> Option<usize> {
if name == "classes.dex" {
return Some(0);
}
name.strip_prefix("classes")
.and_then(|name| name.strip_suffix(".dex"))
.and_then(|name| name.parse::<usize>().ok())
.and_then(|idx| if idx <= 1 { None } else { Some(idx - 1) })
} }