Skip to content
67 changes: 27 additions & 40 deletions apk/src/compiler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::num::NonZeroU8;

use crate::manifest::AndroidManifest;
use crate::res::{
Chunk, ResTableConfig, ResTableEntry, ResTableHeader, ResTablePackageHeader,
ResTableTypeHeader, ResTableTypeSpecHeader, ResTableValue, ResValue, ScreenType,
Chunk, ResTableConfig, ResTableEntry, ResTableHeader, ResTablePackageHeader, ResTableValue,
ResValue, ScreenType,
};
use anyhow::Result;

Expand Down Expand Up @@ -42,52 +44,37 @@ pub fn compile_mipmap<'a>(package_name: &str, name: &'a str) -> Result<Mipmap<'a
vec![
Chunk::StringPool(vec!["mipmap".to_string()], vec![]),
Chunk::StringPool(vec!["icon".to_string()], vec![]),
Chunk::TableTypeSpec(
ResTableTypeSpecHeader {
id: 1,
res0: 0,
res1: 0,
entry_count: 1,
},
vec![256],
),
mipmap_table_type(1, 160, 0),
mipmap_table_type(1, 240, 1),
mipmap_table_type(1, 320, 2),
mipmap_table_type(1, 480, 3),
mipmap_table_type(1, 640, 4),
Chunk::TableTypeSpec(NonZeroU8::new(1).unwrap(), vec![256]),
mipmap_table_type(NonZeroU8::new(1).unwrap(), 160, 0),
mipmap_table_type(NonZeroU8::new(1).unwrap(), 240, 1),
mipmap_table_type(NonZeroU8::new(1).unwrap(), 320, 2),
mipmap_table_type(NonZeroU8::new(1).unwrap(), 480, 3),
mipmap_table_type(NonZeroU8::new(1).unwrap(), 640, 4),
],
),
],
);
Ok(Mipmap { name, chunk })
}

fn mipmap_table_type(type_id: u8, density: u16, string_id: u32) -> Chunk {
Chunk::TableType(
ResTableTypeHeader {
id: type_id,
res0: 0,
res1: 0,
entry_count: 1,
entries_start: 88,
config: ResTableConfig {
size: 28 + 36,
imsi: 0,
locale: 0,
screen_type: ScreenType {
orientation: 0,
touchscreen: 0,
density,
},
input: 0,
screen_size: 0,
version: 4,
unknown: vec![0; 36],
fn mipmap_table_type(type_id: NonZeroU8, density: u16, string_id: u32) -> Chunk {
Chunk::TableType {
type_id,
config: ResTableConfig {
size: 28 + 36,
imsi: 0,
locale: 0,
screen_type: ScreenType {
orientation: 0,
touchscreen: 0,
density,
},
input: 0,
screen_size: 0,
version: 4,
unknown: vec![0; 36],
},
vec![0],
vec![Some(ResTableEntry {
entries: vec![Some(ResTableEntry {
size: 8,
flags: 0,
key: 0,
Expand All @@ -98,7 +85,7 @@ fn mipmap_table_type(type_id: u8, density: u16, string_id: u32) -> Chunk {
data: string_id,
}),
})],
)
}
}

pub struct Mipmap<'a> {
Expand Down
21 changes: 13 additions & 8 deletions apk/src/compiler/table.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::res::{Chunk, ResAttributeType, ResTableEntry, ResTableRef, ResTableValue, ResValue};
use anyhow::{Context, Result};
use std::io::Cursor;
use std::num::NonZeroU8;
use std::path::Path;

pub struct Ref<'a> {
Expand Down Expand Up @@ -70,13 +71,13 @@ impl<'a> Package<'a> {
})
}

fn lookup_type_id(&self, name: &str) -> Result<u8> {
fn lookup_type_id(&self, name: &str) -> Result<NonZeroU8> {
let id = self
.types
.iter()
.position(|s| s.as_str() == name)
.with_context(|| format!("failed to locate type id {name}"))?;
Ok(id as u8 + 1)
NonZeroU8::new(id as u8 + 1).context("overflow")
}

fn lookup_key_id(&self, name: &str) -> Result<u32> {
Expand All @@ -88,10 +89,13 @@ impl<'a> Package<'a> {
Ok(id as u32)
}

fn lookup_type(&self, id: u8) -> Result<Type<'a>> {
fn lookup_type(&self, id: NonZeroU8) -> Result<Type<'a>> {
for chunk in self.chunks {
if let Chunk::TableType(header, _offsets, entries) = chunk {
if header.id == id {
if let Chunk::TableType {
type_id, entries, ..
} = chunk
{
if *type_id == id {
return Ok(Type {
package: self.id,
id,
Expand All @@ -106,7 +110,7 @@ impl<'a> Package<'a> {

struct Type<'a> {
package: u8,
id: u8,
id: NonZeroU8,
entries: &'a [Option<ResTableEntry>],
}

Expand Down Expand Up @@ -191,6 +195,7 @@ pub struct Table {

impl Table {
pub fn import_apk(&mut self, apk: &Path) -> Result<()> {
tracing::trace!("Parse `resources.arsc` chunk from `{apk:?}`");
let resources = xcommon::extract_zip_file(apk, "resources.arsc")?;
let chunk = Chunk::parse(&mut Cursor::new(resources))?;
self.import_chunk(&chunk);
Expand Down Expand Up @@ -218,7 +223,7 @@ impl Table {
}
}

fn lookup_package(&self, id: u8) -> Result<Package> {
fn lookup_package(&self, id: u8) -> Result<Package<'_>> {
for package in &self.packages {
if let Chunk::TablePackage(header, chunks) = package {
if header.id == id as u32 {
Expand All @@ -229,7 +234,7 @@ impl Table {
anyhow::bail!("failed to locate package {}", id);
}

pub fn entry_by_ref(&self, r: Ref) -> Result<Entry> {
pub fn entry_by_ref(&self, r: Ref) -> Result<Entry<'_>> {
let id = self.lookup_package_id(r.package)?;
let package = self.lookup_package(id)?;
let id = package.lookup_type_id(r.ty)?;
Expand Down
Loading
Loading