//! 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; /// The map item: https://source.android.com/docs/core/runtime/dex-format#map-list /// alignment: 4 bytes #[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