xabc_lib/
field.rs

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    /// ClassRegionIndex 的一个索引
14    type_idx: uint16_t,
15    /// 名字的偏移量,指向一个 String
16    name_off: uint32_t,
17    /// 它的值必须是 AccessFlag 的组合。
18    access_flags: Vec<String>,
19    // field_data: Vec<TaggedValue>,
20    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        // 解析 field_data
35        // TODO: 数据保存
36        '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                // field_data: Vec::new(),
89                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}