use crate::{EncodedValue, Error, ReadSeek, Result, Serializable, Uleb128}; use log::warn; use std::io::Write; // To derive Serializable use crate as androscalpel_serializer; /// #[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) } } /// #[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 { warn!( "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 more tests #[cfg(test)] mod test { use super::*; const ENCODED_ANNOTATION_RAW: &[u8] = &[ 0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f, ]; const ENCODED_ANNOTATION_RAW_2: &[u8] = &[0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f]; const ENCODED_ANNOTATION_RAW_3: &[u8] = &[0xbf, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x38, 0x38, 0x02]; const ANNOTATION_ELEMENT_RAW: &[u8] = &[ 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f, ]; const ENCODED_VALUE_RAW: &[u8] = &[0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f]; #[test] fn deserialize_encoded_annotation() { assert_eq!( EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW_3).unwrap(), EncodedAnnotation { type_idx: Uleb128(7103), elements: vec![AnnotationElement { name_idx: Uleb128(53160), value: EncodedValue::Type(0x0238) }], } ); assert_eq!( EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW_2).unwrap(), EncodedAnnotation { type_idx: Uleb128(6646), elements: vec![AnnotationElement { name_idx: Uleb128(46163), value: EncodedValue::Boolean(true) }], } ); assert_eq!( EncodedAnnotation::deserialize_from_slice(ENCODED_ANNOTATION_RAW).unwrap(), EncodedAnnotation { type_idx: Uleb128(7102), elements: vec![AnnotationElement { name_idx: Uleb128(53160), value: EncodedValue::Annotation(EncodedAnnotation { type_idx: Uleb128(6646), elements: vec![AnnotationElement { name_idx: Uleb128(46163), value: EncodedValue::Boolean(true) }] }) }], } ); } #[test] fn serialize_encoded_annotation() { assert_eq!( ENCODED_ANNOTATION_RAW_2, EncodedAnnotation { type_idx: Uleb128(6646), elements: vec![AnnotationElement { name_idx: Uleb128(46163), value: EncodedValue::Boolean(true) }], } .serialize_to_vec() .unwrap() .as_slice() ); assert_eq!( ENCODED_ANNOTATION_RAW, EncodedAnnotation { type_idx: Uleb128(7102), elements: vec![AnnotationElement { name_idx: Uleb128(53160), value: EncodedValue::Annotation(EncodedAnnotation { type_idx: Uleb128(6646), elements: vec![AnnotationElement { name_idx: Uleb128(46163), value: EncodedValue::Boolean(true) }] }) }], } .serialize_to_vec() .unwrap() .as_slice() ); } #[test] fn deserialize_annotation_element() { assert_eq!( AnnotationElement::deserialize_from_slice(ANNOTATION_ELEMENT_RAW).unwrap(), AnnotationElement { name_idx: Uleb128(53160), value: EncodedValue::deserialize_from_slice(ENCODED_VALUE_RAW).unwrap(), } ); } #[test] fn serialize_annotation_element() { assert_eq!( ANNOTATION_ELEMENT_RAW, AnnotationElement { name_idx: Uleb128(53160), value: EncodedValue::deserialize_from_slice(ENCODED_VALUE_RAW).unwrap(), } .serialize_to_vec() .unwrap() .as_slice(), ); } }