xabc_lib/
class.rs

1use std::collections::HashMap;
2
3use crate::field::Field;
4use crate::method::Method;
5
6use crate::{error, string::ABCString, uint32_t};
7use getset::Getters;
8use scroll::ctx;
9use scroll::Pread;
10use scroll::Uleb128;
11use tracing::debug;
12
13#[derive(Debug, Getters)]
14#[get = "pub"]
15pub struct ForeignClass {
16    name: ABCString,
17}
18
19impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for ForeignClass {
20    type Error = error::Error;
21    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
22        let name = source.pread::<ABCString>(0).unwrap();
23
24        Ok((ForeignClass { name }, source.len()))
25    }
26}
27
28#[derive(Debug, Getters)]
29#[get = "pub"]
30pub struct Class {
31    offset: usize,
32    /// 类名
33    #[get = "pub"]
34    name: ABCString,
35    supper_class: String,
36    /// 类的访问标志
37    access_flags: Vec<String>,
38    num_fields: u64,
39    num_methods: u64,
40    // class_data: Vec<TaggedValue>,
41    fields: Vec<Field>,
42    // methods: Vec<Method>,
43    method_map: HashMap<usize, Method>,
44}
45
46impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Class {
47    type Error = error::Error;
48    fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
49        let mut off = 0;
50        let name = source.pread::<ABCString>(0).unwrap();
51        off += name.length();
52
53        let supper_class_off = source.pread::<uint32_t>(off).unwrap();
54        let mut supper_class = String::new();
55        if supper_class_off != 0 {
56            let str = source
57                .pread::<ABCString>(supper_class_off as usize)
58                .unwrap();
59            supper_class = str.str();
60        }
61        off += 4;
62
63        let off = &mut off;
64        let access_flags = Uleb128::read(source, off).unwrap();
65        let access_flags = ClassAccessFlags::parse(access_flags);
66        let num_fields = Uleb128::read(source, off).unwrap();
67        let num_methods = Uleb128::read(source, off).unwrap();
68
69        // let mut offset = *off;
70        // TODO: ClassData
71        'l: loop {
72            let tag_value = source.pread::<u8>(*off).unwrap();
73            *off += 1;
74            match tag_value {
75                0x00 => {
76                    debug!("NOTHING: exit");
77                    break 'l;
78                }
79                0x01 => {
80                    debug!("INTERFACES");
81                }
82                0x02 => {
83                    let data = source.pread::<u8>(*off).unwrap();
84                    *off += 1;
85                    debug!("SOURCE_LANG -> {}", data);
86                }
87                0x03 => {
88                    debug!("RUNTIME_ANNOTATION");
89                }
90                0x04 => {
91                    debug!("ANNOTATION");
92                }
93                0x05 => {
94                    debug!("RUNTIME_TYPE_ANNOTATION");
95                }
96                0x06 => {
97                    debug!("TYPE_ANNOTATION");
98                }
99                0x07 => {
100                    debug!("SOURCE_FILE");
101                }
102                _ => {
103                    tracing::error!("Error! -> UNKNOWN: {}", tag_value);
104                    break 'l;
105                }
106            }
107        }
108
109        let mut offset = *off;
110        let mut fields = Vec::new();
111        for _ in 0..num_fields {
112            let field = source.pread::<Field>(offset).unwrap();
113            let size = *field.size();
114            offset += size;
115            fields.push(field);
116        }
117
118        // let mut methods = Vec::new();
119        let mut method_map = HashMap::new();
120        for _ in 0..num_methods {
121            // TODO: 记录这个offset,并且保存起来,未来建立一个 map
122            let method = source.pread::<Method>(offset).unwrap();
123
124            let size = *method.size();
125            offset += size;
126
127            method_map.insert(offset, method);
128            // methods.push(method);
129        }
130
131        Ok((
132            Class {
133                offset,
134                name,
135                supper_class,
136                access_flags,
137                num_fields,
138                num_methods,
139                fields,
140                // methods,
141                method_map,
142            },
143            source.len(),
144        ))
145    }
146}
147
148impl Class {
149    pub fn has_method(&self, offset: usize) -> bool {
150        self.method_map.contains_key(&offset)
151    }
152
153    pub fn get_method(&self, offset: usize) -> Option<&Method> {
154        self.method_map.get(&offset)
155    }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159enum ClassAccessFlags {
160    Public = 0x0001,
161    Final = 0x0010,
162    Super = 0x0020,
163    Interface = 0x0200,
164    Abstract = 0x0400,
165    Synthetic = 0x1000,
166    Annotation = 0x2000,
167    Enum = 0x4000,
168}
169
170impl ClassAccessFlags {
171    pub fn parse(value: u64) -> Vec<String> {
172        let mut access_flags: Vec<String> = Vec::new();
173
174        let flags = [
175            ClassAccessFlags::Public,
176            ClassAccessFlags::Final,
177            ClassAccessFlags::Super,
178            ClassAccessFlags::Interface,
179            ClassAccessFlags::Abstract,
180            ClassAccessFlags::Synthetic,
181            ClassAccessFlags::Annotation,
182            ClassAccessFlags::Enum,
183        ]
184        .to_vec();
185
186        for flag in flags {
187            let x = flag as u64;
188            if value & x != 0 {
189                //println!("{:?}", flag);
190                access_flags.push(format!("{:?}", flag));
191            }
192        }
193
194        access_flags
195    }
196}