//! Annotation items. pub mod encoded_annotation; pub use encoded_annotation::*; use crate as androscalpel_serializer; use crate::{ReadSeek, Result, Serializable}; use std::io::Write; /// /// alignment: 4 bytes #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationDirectoryItem { /// 0 if they are no annotation, else offset of an [`crate::AnnotationSetItem`]. pub class_annotations_off: u32, // pub fields_size: u32, // pub annotated_methods_size: u32, // pub annotated_parameters_size: u32, /// List of field annotation. The field annotations must be sorted by /// increasing order of [`crate::FieldAnnotation.field_idx`]. pub field_annotations: Vec, /// List of method annotation. The method annotations must be sorted by /// increasing order of [`crate::MethodAnnotation.method_idx`]. pub method_annotation: Vec, /// List of associated method parameter annotation. The parameter annotations /// must be sorted by increasing order of [`crate::ParameterAnnotation.parameter_size`]. pub parameter_annotations: Vec, } impl AnnotationDirectoryItem { pub fn fields_size_field(&self) -> u32 { self.field_annotations.len() as u32 } pub fn annotated_methods_size_field(&self) -> u32 { self.method_annotation.len() as u32 } pub fn parameter_annotations_field(&self) -> u32 { self.parameter_annotations.len() as u32 } } impl Serializable for AnnotationDirectoryItem { fn serialize(&self, output: &mut dyn Write) -> Result<()> { self.class_annotations_off.serialize(output)?; self.fields_size_field().serialize(output)?; self.annotated_methods_size_field().serialize(output)?; self.parameter_annotations_field().serialize(output)?; for item in &self.field_annotations { item.serialize(output)?; } for item in &self.method_annotation { item.serialize(output)?; } for item in &self.parameter_annotations { item.serialize(output)?; } Ok(()) } fn deserialize(input: &mut dyn ReadSeek) -> Result { let class_annotations_off = u32::deserialize(input)?; let fields_size = u32::deserialize(input)?; let annotated_methods_size = u32::deserialize(input)?; let annotated_parameters_size = u32::deserialize(input)?; let mut field_annotations = vec![]; for _ in 0..fields_size { field_annotations.push(FieldAnnotation::deserialize(input)?); } let mut method_annotation = vec![]; for _ in 0..annotated_methods_size { method_annotation.push(MethodAnnotation::deserialize(input)?); } let mut parameter_annotations = vec![]; for _ in 0..annotated_parameters_size { parameter_annotations.push(ParameterAnnotation::deserialize(input)?); } Ok(Self { class_annotations_off, field_annotations, method_annotation, parameter_annotations, }) } fn size(&self) -> usize { self.class_annotations_off.size() + self.fields_size_field().size() + self.annotated_methods_size_field().size() + self.parameter_annotations_field().size() + self .field_annotations .iter() .map(|val| val.size()) .sum::() + self .method_annotation .iter() .map(|val| val.size()) .sum::() + self .parameter_annotations .iter() .map(|val| val.size()) .sum::() } } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct FieldAnnotation { pub field_idx: u32, /// Offset to a [`AnnotationSetItem`] pub annotation_off: u32, } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct MethodAnnotation { pub method_idx: u32, /// Offset to a [`AnnotationSetItem`] pub annotation_off: u32, } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct ParameterAnnotation { pub field_idx: u32, /// Offset of a [`AnnotationSetRefList`] pub annotation_off: u32, } /// /// alignment: 4 bytes #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationSetRefList { // pub size: u32, pub list: Vec, } impl AnnotationSetRefList { pub fn size_field(&self) -> u32 { self.list.len() as u32 } } impl Serializable for AnnotationSetRefList { fn serialize(&self, output: &mut dyn Write) -> Result<()> { self.size_field().serialize(output)?; for item in &self.list { 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(AnnotationSetRefItem::deserialize(input)?); } Ok(Self { list }) } fn size(&self) -> usize { self.size_field().size() + self.list.iter().map(|val| val.size()).sum::() } } /// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct AnnotationSetRefItem { /// 0 if there are no annotation, offset to a [`AnnotationSetItem`] else. pub annotations_off: u32, } /// /// alignment: 4 #[derive(Debug, Clone, PartialEq, Eq)] pub struct AnnotationSetItem { // pub size: u32, /// Must be sorted by increasing [`AnnotationOffItem.type_idx`]. pub entries: Vec, } impl AnnotationSetItem { pub fn size_field(&self) -> u32 { self.entries.len() as u32 } } impl Serializable for AnnotationSetItem { fn serialize(&self, output: &mut dyn Write) -> Result<()> { self.size_field().serialize(output)?; for item in &self.entries { item.serialize(output)?; } Ok(()) } fn deserialize(input: &mut dyn ReadSeek) -> Result { let size = u32::deserialize(input)?; let mut entries = vec![]; for _ in 0..size { entries.push(AnnotationOffItem::deserialize(input)?); } Ok(Self { entries }) } fn size(&self) -> usize { self.size_field().size() + self.entries.iter().map(|val| val.size()).sum::() } } /// #[derive(Serializable, Debug, Clone, Copy, PartialEq, Eq)] pub struct AnnotationOffItem { /// Offset to a [`crate::AnnotationItem`] pub annotation_off: u32, } /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] pub struct AnnotationItem { pub visibility: AnnotationVisibility, pub annotation: EncodedAnnotation, } // TODO: Enum or flags ? /// #[derive(Serializable, Debug, Clone, PartialEq, Eq)] #[prefix_type(u8)] pub enum AnnotationVisibility { #[prefix(0x00)] Build, #[prefix(0x01)] Runtime, #[prefix(0x02)] System, } #[cfg(test)] mod test { use super::*; const ANNOTATION_ITEM: &[u8] = &[ 0x02, 0xbe, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x1d, 0xf6, 0x33, 0x01, 0xd3, 0xe8, 0x02, 0x3f, ]; const ANNOTATION_ITEM_2: &[u8] = &[0x02, 0xbf, 0x37, 0x01, 0xa8, 0x9f, 0x03, 0x38, 0x38, 0x02]; #[test] fn deserialize_annotation_item() { assert_eq!( AnnotationItem::deserialize_from_slice(ANNOTATION_ITEM).unwrap(), AnnotationItem { visibility: AnnotationVisibility::System, annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM[1..]) .unwrap(), } ); assert_eq!( AnnotationItem::deserialize_from_slice(ANNOTATION_ITEM_2).unwrap(), AnnotationItem { visibility: AnnotationVisibility::System, annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM_2[1..]) .unwrap(), } ); } #[test] fn serialize_annotation_item() { assert_eq!( ANNOTATION_ITEM, AnnotationItem { visibility: AnnotationVisibility::System, annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM[1..]) .unwrap(), } .serialize_to_vec() .unwrap() .as_slice() ); assert_eq!( ANNOTATION_ITEM_2, AnnotationItem { visibility: AnnotationVisibility::System, annotation: EncodedAnnotation::deserialize_from_slice(&ANNOTATION_ITEM_2[1..]) .unwrap(), } .serialize_to_vec() .unwrap() .as_slice() ); } }