lvm_class/attribute/
type_annotation.rs1use super::annotation::ElementValuePair;
6use crate::ClassFormatErr;
7use lvm_common::utils::cursor::ByteCursor;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum TargetInfo {
12 TypeParameter {
13 type_parameter_index: u8,
14 },
15 Supertype {
16 supertype_index: u16,
17 },
18 TypeParameterBound {
19 type_parameter_index: u8,
20 bound_index: u8,
21 },
22 Empty,
23 MethodFormalParameter {
24 formal_parameter_index: u8,
25 },
26 Throws {
27 throws_type_index: u16,
28 },
29 LocalVar {
30 localvar_table: Vec<LocalVarEntry>,
31 },
32 Catch {
33 exception_table_index: u16,
34 },
35 Offset {
36 offset: u16,
37 },
38 TypeArgument {
39 offset: u16,
40 type_argument_index: u8,
41 },
42}
43
44#[derive(Debug, Clone, PartialEq, Eq)]
46pub struct LocalVarEntry {
47 pub start_pc: u16,
48 pub length: u16,
49 pub index: u16,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct TypePath {
55 pub path: Vec<TypePathEntry>,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct TypePathEntry {
61 pub type_path_kind: u8,
62 pub type_argument_index: u8,
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct TypeAnnotation {
70 pub target_info: TargetInfo,
71 pub target_path: TypePath,
72 pub type_index: u16,
73 pub element_value_pairs: Vec<ElementValuePair>,
74}
75
76impl<'a> TypeAnnotation {
77 pub(crate) fn read(cursor: &mut ByteCursor<'a>) -> Result<Self, ClassFormatErr> {
78 let target_type = cursor.u8()?;
79
80 let target_info = match target_type {
81 0x00 => TargetInfo::TypeParameter {
82 type_parameter_index: cursor.u8()?,
83 },
84 0x01 => TargetInfo::Supertype {
85 supertype_index: cursor.u16()?,
86 },
87 0x10 => TargetInfo::TypeParameterBound {
88 type_parameter_index: cursor.u8()?,
89 bound_index: cursor.u8()?,
90 },
91 0x11 => TargetInfo::Empty,
92 0x12 => TargetInfo::MethodFormalParameter {
93 formal_parameter_index: cursor.u8()?,
94 },
95 0x13 => TargetInfo::Throws {
96 throws_type_index: cursor.u16()?,
97 },
98 0x14 => {
99 let table_length = cursor.u16()?;
100 let mut localvar_table = Vec::with_capacity(table_length as usize);
101 for _ in 0..table_length {
102 localvar_table.push(LocalVarEntry {
103 start_pc: cursor.u16()?,
104 length: cursor.u16()?,
105 index: cursor.u16()?,
106 });
107 }
108 TargetInfo::LocalVar { localvar_table }
109 }
110 0x15 => TargetInfo::Catch {
111 exception_table_index: cursor.u16()?,
112 },
113 0x16 => TargetInfo::Offset {
114 offset: cursor.u16()?,
115 },
116 0x17 => TargetInfo::TypeArgument {
117 offset: cursor.u16()?,
118 type_argument_index: cursor.u8()?,
119 },
120 _ => unimplemented!(),
121 };
122
123 let path_length = cursor.u8()?;
125 let mut path = Vec::with_capacity(path_length as usize);
126 for _ in 0..path_length {
127 path.push(TypePathEntry {
128 type_path_kind: cursor.u8()?,
129 type_argument_index: cursor.u8()?,
130 });
131 }
132 let target_path = TypePath { path };
133
134 let type_index = cursor.u16()?;
136 let num_element_value_pairs = cursor.u16()?;
137 let mut element_value_pairs = Vec::with_capacity(num_element_value_pairs as usize);
138 for _ in 0..num_element_value_pairs {
139 element_value_pairs.push(ElementValuePair::read(cursor)?);
140 }
141
142 Ok(Self {
143 target_info,
144 target_path,
145 type_index,
146 element_value_pairs,
147 })
148 }
149}