1use getset::Getters;
2use scroll::ctx;
3use scroll::Pread;
4use scroll::Sleb128;
5use scroll::Uleb128;
6
7use crate::{error, uint16_t, uint32_t};
8
9#[derive(Debug, Getters, Default)]
10#[get = "pub"]
11pub struct Field {
12 class_idx: uint16_t,
13 type_idx: uint16_t,
15 name_off: uint32_t,
17 access_flags: Vec<String>,
19 size: usize,
21}
22
23impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Field {
24 type Error = error::Error;
25 fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
26 let class_idx = source.pread::<uint16_t>(0).unwrap();
27 let type_idx = source.pread::<uint16_t>(2).unwrap();
28 let name_off = source.pread::<uint32_t>(4).unwrap();
29
30 let off = &mut 8;
31 let access_flags = Uleb128::read(source, off).unwrap();
32 let access_flags = FieldAccessFlag::parse(access_flags);
33
34 'l: loop {
37 let tag_value = source.pread::<u8>(*off).unwrap();
38 *off += 1;
39 match tag_value {
40 0x00 => {
41 tracing::debug!("NOTHING");
42 break 'l;
43 }
44 0x01 => {
45 let num = Sleb128::read(source, off).unwrap();
46 tracing::debug!("INT_VALUE -> {}", num);
47 }
48 0x02 => {
49 let data = source.pread::<uint32_t>(*off).unwrap();
50 *off += 4;
51 tracing::debug!("VALUE -> {}", data);
52 }
53 0x03 => {
54 let data = source.pread::<uint32_t>(*off).unwrap();
55 *off += 4;
56 tracing::debug!("RUNTIME_ANNOTATIONS -> {}", data);
57 }
58 0x04 => {
59 let data = source.pread::<uint32_t>(*off).unwrap();
60 *off += 4;
61 tracing::debug!("ANNOTATIONS -> {}", data);
62 }
63 0x05 => {
64 let data = source.pread::<uint32_t>(*off).unwrap();
65 *off += 4;
66 tracing::debug!("RUNTIME_TYPE_ANNOTATION -> {}", data);
67 }
68 0x06 => {
69 let data = source.pread::<uint32_t>(*off).unwrap();
70 *off += 4;
71 tracing::debug!("TYPE_ANNOTATION -> {}", data);
72 }
73 _ => {
74 tracing::debug!("UNKNOWN: {}", tag_value);
75 break 'l;
76 }
77 }
78 }
79
80 let size = *off;
81
82 Ok((
83 Field {
84 class_idx,
85 type_idx,
86 name_off,
87 access_flags,
88 size,
90 },
91 source.len(),
92 ))
93 }
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub enum FieldAccessFlag {
98 PUBLIC = 0x0001,
99 PRIVATE = 0x0002,
100 PROTECTED = 0x0004,
101 STATIC = 0x0008,
102 FINAL = 0x0010,
103 VOLATILE = 0x0040,
104 TRANSIENT = 0x0080,
105 SYNTHETIC = 0x1000,
106 ENUM = 0x4000,
107}
108
109impl FieldAccessFlag {
110 pub fn parse(value: u64) -> Vec<String> {
111 let mut access_flags: Vec<String> = Vec::new();
112
113 let flags = [
114 FieldAccessFlag::PUBLIC,
115 FieldAccessFlag::PRIVATE,
116 FieldAccessFlag::PROTECTED,
117 FieldAccessFlag::STATIC,
118 FieldAccessFlag::FINAL,
119 FieldAccessFlag::VOLATILE,
120 FieldAccessFlag::TRANSIENT,
121 FieldAccessFlag::SYNTHETIC,
122 FieldAccessFlag::ENUM,
123 ]
124 .to_vec();
125
126 for flag in flags {
127 let x = flag as u64;
128 if value & x != 0 {
129 access_flags.push(format!("{:?}", flag));
130 }
131 }
132
133 access_flags
134 }
135}