xabc_lib/
region.rs

1/// 索引结构,用于存放索引信息,根据索引信息可以快速定位到对应的数据。
2use getset::{CopyGetters, Getters};
3use scroll::Pread;
4use std::fmt;
5
6use crate::uint32_t;
7
8#[derive(Debug, Pread, CopyGetters)]
9#[get_copy = "pub"]
10pub struct RegionHeader {
11    /// 该区域的起始偏移量。
12    start_off: uint32_t,
13    /// 该区域的结束偏移量。
14    end_off: uint32_t,
15    /// 该区域的 ClassRegionIndex 中元素的数量,最大值为65536。
16    class_idx_size: uint32_t,
17    /// 一个偏移量,指向 ClassRegionIndex。
18    class_idx_off: uint32_t,
19    /// MethodStringLiteralRegionIndex 的数量
20    method_string_literal_region_idx_size: uint32_t,
21    /// 指向方法、字符串或者字面量数组。
22    method_string_literal_region_idx_off: uint32_t,
23    // 0XFFFFFFFF 表示无
24    /// FieldRegionIndex
25    field_idx_size: uint32_t,
26    field_idx_off: uint32_t,
27    /// ProtoRegionIndex
28    proto_idx_size: uint32_t,
29    proto_idx_off: uint32_t,
30}
31
32/// 存放类型,如果不是基础类型,那么就是一个指向Class的偏移量
33//pub type FieldType = uint32_t;
34
35#[derive(Debug, CopyGetters, Getters, Default)]
36#[get = "pub"]
37pub struct FieldType {
38    // TODO: 如果类的数量特别多的话,会不会重复占用内存?
39    // TODO: 也许可以增加一个 benchmark 来验证一下
40    pub name: String,
41}
42
43impl fmt::Display for FieldType {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        write!(f, "{}", self.name)
46    }
47}
48
49#[derive(Debug, Default)]
50pub struct ClassRegionIndex {
51    // 一个数组,数组中每个元素都是Type类型。
52    offsets: Vec<FieldType>,
53}
54
55impl ClassRegionIndex {
56    pub fn push(&mut self, field_type: FieldType) {
57        self.offsets.push(field_type);
58    }
59
60    pub fn get(&self, idx: &usize) -> &FieldType {
61        &self.offsets[*idx]
62    }
63}
64
65#[derive(Debug, Getters, Default)]
66#[get = "pub"]
67pub struct MethodStringLiteralRegionIndex {
68    offsets: Vec<uint32_t>,
69}
70
71impl MethodStringLiteralRegionIndex {
72    pub fn push(&mut self, offset: uint32_t) {
73        self.offsets.push(offset);
74    }
75
76    pub fn get(&self, idx: &usize) -> &uint32_t {
77        &self.offsets[*idx]
78    }
79}
80
81#[derive(Debug, Getters, Default)]
82#[get = "pub"]
83pub struct FieldRegionIndex {
84    offsets: Vec<uint32_t>,
85}
86
87impl FieldRegionIndex {
88    pub fn push(&mut self, offset: uint32_t) {
89        self.offsets.push(offset);
90    }
91}
92
93#[derive(Debug, Getters, Default)]
94#[get = "pub"]
95pub struct ProtoRegionIndex {
96    offsets: Vec<uint32_t>,
97}
98
99impl ProtoRegionIndex {
100    pub fn push(&mut self, offset: uint32_t) {
101        self.offsets.push(offset);
102    }
103}
104
105#[derive(Debug, Getters)]
106#[get = "pub"]
107pub struct Region {
108    header: RegionHeader,
109    /// 通过索引找到类型 FieldType
110    class_region_idx: ClassRegionIndex,
111    /// 找到对应的方法、字符串或者字面量数组。
112    method_string_literal_region_idx: MethodStringLiteralRegionIndex,
113    field_region_idx: FieldRegionIndex,
114    proto_region_idx: ProtoRegionIndex,
115}
116
117impl Region {
118    pub fn new(
119        header: RegionHeader,
120        cri: ClassRegionIndex,
121        mslri: MethodStringLiteralRegionIndex,
122        field_region_idx: FieldRegionIndex,
123        proto_region_idx: ProtoRegionIndex,
124    ) -> Self {
125        Self {
126            header,
127            class_region_idx: cri,
128            method_string_literal_region_idx: mslri,
129            field_region_idx,
130            proto_region_idx,
131        }
132    }
133
134    /// 数据是否在这个区域内
135    pub fn is_here(&self, off: usize) -> bool {
136        self.header.start_off() as usize <= off && off < self.header.end_off() as usize
137    }
138
139    /// 根据索引获取它的类型
140    // 只有一个地方用到,解析方法的时候,有一个。
141    pub fn get_class_name(&self, idx: usize) -> &FieldType {
142        self.class_region_idx.get(&idx)
143    }
144
145    /// 根据索引获取它的偏移量
146    pub fn get_msl_offset(&self, idx: usize) -> &uint32_t {
147        self.method_string_literal_region_idx.get(&idx)
148    }
149}