diff --git a/androscalpel_serializer/src/items/map.rs b/androscalpel_serializer/src/items/map.rs new file mode 100644 index 0000000..9fba630 --- /dev/null +++ b/androscalpel_serializer/src/items/map.rs @@ -0,0 +1,100 @@ +//! The map item: https://source.android.com/docs/core/runtime/dex-format#map-list + +use crate as androscalpel_serializer; +use crate::core::{ReadSeek, Result, Serializable}; +use std::io::Write; + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct MapList { + // pub size: u32, + pub list: Vec, +} + +/// The location and size of an item: https://source.android.com/docs/core/runtime/dex-format#map-item +#[derive(Serializable, Clone, PartialEq, Eq, Debug)] +pub struct MapItem { + pub type_: MapItemType, + pub unused: u16, + pub size: u32, + pub offset: u32, +} + +/// The type of the items refered by a [`MapItem`]: https://source.android.com/docs/core/runtime/dex-format#type-codes +#[derive(Serializable, Clone, Copy, PartialEq, Eq, Debug)] +#[prefix_type(u16)] +pub enum MapItemType { + #[prefix(0x0000)] + HeaderItem, + #[prefix(0x0001)] + StringIdItem, + #[prefix(0x0002)] + TypeIdItem, + #[prefix(0x0003)] + ProtoIdItem, + #[prefix(0x0004)] + FieldIdItem, + #[prefix(0x0005)] + MethodIdItem, + #[prefix(0x0006)] + ClassDefItem, + #[prefix(0x0007)] + CallSiteIdItem, + #[prefix(0x0008)] + MethodHandleItem, + #[prefix(0x1000)] + MapList, + #[prefix(0x1001)] + TypeList, + #[prefix(0x1002)] + AnnotationSetRefList, + #[prefix(0x1003)] + AnnotationSetItem, + #[prefix(0x2000)] + ClassDataItem, + #[prefix(0x2001)] + CodeItem, + #[prefix(0x2002)] + StringDataItem, + #[prefix(0x2003)] + DebugInfoItem, + #[prefix(0x2004)] + AnnotationItem, + #[prefix(0x2005)] + EncodedArrayItem, + #[prefix(0x2006)] + AnnotationsDirectoryItem, + #[prefix(0xF000)] + HiddenapiClassDataItem, +} + +impl MapList { + /// The size field of a MapList. + pub fn size_field(&self) -> u32 { + self.list.len() as u32 + } +} + +impl Serializable for MapList { + fn serialize(&self, output: &mut dyn Write) -> Result<()> { + self.size_field().serialize(output)?; + for map_item in self.list { + map_item.serialize(output)?; + } + Ok(()) + } + + fn deserialize(input: &mut dyn ReadSeek) -> Result { + let size = u32::deserialize(input)?; + let mut list = vec![]; + for _ in 0..size { + list.push(MapItem::deserialize(input)?); + } + Ok(Self { list }) + } + + fn size(&self) -> usize { + self.size_field().size() + self.list.iter().map(|item| item.size()).sum::() + } +} + +// TODO: add tests diff --git a/androscalpel_serializer/src/lib.rs b/androscalpel_serializer/src/lib.rs index 2776e91..0ec4bef 100644 --- a/androscalpel_serializer/src/lib.rs +++ b/androscalpel_serializer/src/lib.rs @@ -2,6 +2,7 @@ pub mod annotation; pub mod array; pub mod constant; pub mod core; +pub mod items; pub mod value; pub use androscalpel_serializer_derive::*; @@ -10,4 +11,5 @@ pub use crate::core::*; pub use annotation::*; pub use array::*; pub use constant::*; +pub use items::*; pub use value::*;