use crate::{EncodedValue, Error, ReadSeek, Result, Serializable, Uleb128}; use std::io::Write; // To derive Serializable use crate as androscalpel_serializer; /// Encoded Annotation https://source.android.com/docs/core/runtime/dex-format#encoded-annotation #[derive(Debug, Clone, PartialEq, Eq)] pub struct EncodedAnnotation { /// Type of the annotation. This must be a class (not array or primitive) type. pub type_idx: Uleb128, // TODO: check it's a class //pub size: Uleb128, pub elements: Vec, } impl EncodedAnnotation { /// Return the size field pub fn size_field(&self) -> Uleb128 { Uleb128(self.elements.len() as u32) } } /// Annotation: https://source.android.com/docs/core/runtime/dex-format#annotation-element #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct AnnotationElement { pub name_idx: Uleb128, pub value: EncodedValue, } impl Serializable for EncodedAnnotation { fn serialize(&self, output: &mut dyn Write) -> Result<()> { let Self { type_idx, elements } = self; // Check if the element are sorted if !elements.is_empty() { let mut idx_0 = elements[0].name_idx; for idx_1 in elements.iter().map(|elt| elt.name_idx).skip(1) { if idx_0 > idx_1 { return Err(Error::SerializationError(format!( "Failed to serialize EncodedAnnotation: element must be sorted in increasing order by string_id index, found {idx_0:?} before {idx_1:?}" ))); } idx_0 = idx_1; } } type_idx.serialize(output)?; self.size_field().serialize(output)?; for elt in elements { elt.serialize(output)?; } Ok(()) } fn deserialize(input: &mut dyn ReadSeek) -> Result { let type_idx = Uleb128::deserialize(input)?; let Uleb128(size) = Uleb128::deserialize(input)?; let mut elements = vec![]; for _ in 0..size { elements.push(AnnotationElement::deserialize(input)?); } if !elements.is_empty() { let mut idx_0 = elements[0].name_idx; for idx_1 in elements.iter().map(|elt| elt.name_idx).skip(1) { if idx_0 > idx_1 { // TODO: use proper logging println!( "Waring while deserializing EncodedAnnotation: element must be sorted in increasing order by string_id index, found {idx_0:?} before {idx_1:?}" ); } idx_0 = idx_1; } } Ok(Self { type_idx, elements }) } fn size(&self) -> usize { self.type_idx.size() + self.size_field().size() + self.elements.iter().map(|val| val.size()).sum::() } } // TODO: add tests