1use crate::reader::Cursor;
8
9#[derive(Debug, Clone)]
10pub enum EncodedValue {
11 Byte(i8),
12 Short(i16),
13 Char(u16),
14 Int(i32),
15 Long(i64),
16 Float(f32),
17 Double(f64),
18 MethodType(u32),
19 MethodHandle(u32),
20 String(u32),
21 Type(u32),
22 Field(u32),
23 Method(u32),
24 Enum(u32),
25 Array(Vec<EncodedValue>),
26 Annotation(EncodedAnnotation),
27 Null,
28 Boolean(bool),
29}
30
31#[derive(Debug, Clone)]
32pub struct EncodedAnnotation {
33 pub type_idx: u32,
34 pub elements: Vec<(u32, EncodedValue)>,
36}
37
38fn little_extend(bytes: &[u8], signed: bool, size: usize) -> i64 {
39 let mut v: u64 = 0;
40 for (i, &b) in bytes.iter().enumerate() {
41 v |= (b as u64) << (8 * i);
42 }
43 if signed {
44 let shift = 64 - 8 * size;
45 v = (v << shift) as i64 as u64 >> shift;
46 }
47 v as i64
48}
49
50pub fn read_encoded_value(data: &[u8], pos: usize) -> Option<(EncodedValue, usize)> {
51 let mut c = Cursor::at(data, pos);
52 let header = c.u1()?;
53 let vtype = header & 0x1f;
54 let varg = (header >> 5) as usize;
55 match vtype {
56 0x00 => {
57 let v = little_extend(take(data, c.pos, varg + 1)?, true, varg + 1);
58 Some((EncodedValue::Byte(v as i8), c.pos + varg + 1 - pos))
59 }
60 0x02 => {
61 let v = little_extend(take(data, c.pos, varg + 1)?, true, varg + 1);
62 Some((EncodedValue::Short(v as i16), c.pos + varg + 1 - pos))
63 }
64 0x03 => {
65 let v = little_extend(take(data, c.pos, varg + 1)?, false, varg + 1);
66 Some((EncodedValue::Char(v as u16), c.pos + varg + 1 - pos))
67 }
68 0x04 => {
69 let v = little_extend(take(data, c.pos, varg + 1)?, true, varg + 1);
70 Some((EncodedValue::Int(v as i32), c.pos + varg + 1 - pos))
71 }
72 0x06 => {
73 let v = little_extend(take(data, c.pos, varg + 1)?, true, varg + 1);
74 Some((EncodedValue::Long(v), c.pos + varg + 1 - pos))
75 }
76 0x10 => {
77 let v = little_extend(take(data, c.pos, varg + 1)?, false, varg + 1);
78 Some((
79 EncodedValue::Float(f32::from_bits(v as u32)),
80 c.pos + varg + 1 - pos,
81 ))
82 }
83 0x11 => {
84 let v = little_extend(take(data, c.pos, varg + 1)?, false, varg + 1);
85 Some((
86 EncodedValue::Double(f64::from_bits(v as u64)),
87 c.pos + varg + 1 - pos,
88 ))
89 }
90 0x15..=0x1b => {
91 let v = little_extend(take(data, c.pos, varg + 1)?, false, varg + 1);
92 let ev = match vtype {
93 0x15 => EncodedValue::MethodType(v as u32),
94 0x16 => EncodedValue::MethodHandle(v as u32),
95 0x17 => EncodedValue::String(v as u32),
96 0x18 => EncodedValue::Type(v as u32),
97 0x19 => EncodedValue::Field(v as u32),
98 0x1a => EncodedValue::Method(v as u32),
99 _ => EncodedValue::Enum(v as u32),
100 };
101 Some((ev, c.pos + varg + 1 - pos))
102 }
103 0x1c => {
104 let n = c.read_uleb128()? as usize;
105 let mut items = Vec::with_capacity(n);
106 let mut p = c.pos;
107 for _ in 0..n {
108 let (v, used) = read_encoded_value(data, p)?;
109 p += used;
110 items.push(v);
111 }
112 Some((EncodedValue::Array(items), p - pos))
113 }
114 0x1d => {
115 let (a, used) = read_encoded_annotation(data, c.pos)?;
116 Some((EncodedValue::Annotation(a), c.pos - pos + used))
117 }
118 0x1e => Some((EncodedValue::Null, 1)),
119 0x1f => Some((EncodedValue::Boolean(varg != 0), 1)),
120 _ => Some((EncodedValue::Null, 1)),
121 }
122}
123
124fn take(data: &[u8], pos: usize, n: usize) -> Option<&[u8]> {
125 if pos + n > data.len() {
126 return None;
127 }
128 Some(&data[pos..pos + n])
129}
130
131pub fn read_encoded_annotation(data: &[u8], pos: usize) -> Option<(EncodedAnnotation, usize)> {
132 let mut c = Cursor::at(data, pos);
133 let type_idx = c.read_uleb128()? as u32;
134 let n = c.read_uleb128()? as usize;
135 let mut elements = Vec::with_capacity(n);
136 let mut p = c.pos;
137 for _ in 0..n {
138 let mut cc = Cursor::at(data, p);
139 let name = cc.read_uleb128()? as u32;
140 p = cc.pos;
141 let (v, used) = read_encoded_value(data, p)?;
142 p += used;
143 elements.push((name, v));
144 }
145 Some((EncodedAnnotation { type_idx, elements }, p - pos))
146}
147
148pub fn read_encoded_array(data: &[u8], pos: usize) -> Option<Vec<EncodedValue>> {
149 let mut c = Cursor::at(data, pos);
150 let n = c.read_uleb128()? as usize;
151 let mut out = Vec::with_capacity(n);
152 let mut p = c.pos;
153 for _ in 0..n {
154 let (v, used) = read_encoded_value(data, p)?;
155 p += used;
156 out.push(v);
157 }
158 Some(out)
159}
160
161pub fn read_class_annotations(data: &[u8], annotations_off: u32) -> Vec<EncodedAnnotation> {
164 let off = annotations_off as usize;
165 if off == 0 || off + 4 > data.len() {
166 return Vec::new();
167 }
168 let set_off = u32::from_le_bytes(data[off..off + 4].try_into().unwrap()) as usize;
169 if set_off == 0 || set_off + 4 > data.len() {
170 return Vec::new();
171 }
172 let n = u32::from_le_bytes(data[set_off..set_off + 4].try_into().unwrap()) as usize;
173 let mut out = Vec::with_capacity(n);
174 for i in 0..n {
175 let p = set_off + 4 + 4 * i;
176 if p + 4 > data.len() {
177 break;
178 }
179 let item_off = u32::from_le_bytes(data[p..p + 4].try_into().unwrap()) as usize;
180 if item_off >= data.len() {
182 continue;
183 }
184 if let Some((a, _)) = read_encoded_annotation(data, item_off + 1) {
185 out.push(a);
186 }
187 }
188 out
189}
190
191#[derive(Debug, Clone, Default)]
193pub struct NestingInfo {
194 pub enclosing_class: Option<u32>,
196 pub enclosing_method: Option<u32>,
198 pub inner_name: Option<u32>,
200 pub member_classes: Vec<u32>,
202}
203
204const DALVIK_ENCLOSING_CLASS: &str = "Ldalvik/annotation/EnclosingClass;";
205const DALVIK_ENCLOSING_METHOD: &str = "Ldalvik/annotation/EnclosingMethod;";
206const DALVIK_INNER_CLASS: &str = "Ldalvik/annotation/InnerClass;";
207const DALVIK_MEMBER_CLASSES: &str = "Ldalvik/annotation/MemberClasses;";
208
209pub fn nesting_from(
211 annotations: &[EncodedAnnotation],
212 type_name: &dyn Fn(u32) -> String,
213) -> NestingInfo {
214 let mut info = NestingInfo::default();
215 for a in annotations {
216 let tname = type_name(a.type_idx);
217 match tname.as_str() {
218 DALVIK_ENCLOSING_CLASS => {
219 for (_, v) in &a.elements {
220 if let EncodedValue::Type(t) = v {
221 info.enclosing_class = Some(*t);
222 }
223 }
224 }
225 DALVIK_ENCLOSING_METHOD => {
226 for (_, v) in &a.elements {
227 if let EncodedValue::Method(m) = v {
228 info.enclosing_method = Some(*m);
229 }
230 }
231 }
232 DALVIK_INNER_CLASS => {
233 for (_, v) in &a.elements {
234 if let EncodedValue::String(s) = v {
235 info.inner_name = Some(*s);
236 }
237 }
238 }
239 DALVIK_MEMBER_CLASSES => {
240 for (_, v) in &a.elements {
241 if let EncodedValue::Array(items) = v {
242 for it in items {
243 if let EncodedValue::Type(t) = it {
244 info.member_classes.push(*t);
245 }
246 }
247 }
248 }
249 }
250 _ => {}
251 }
252 }
253 info
254}