Skip to main content

jvm_assembler/formats/class/writer/
pool.rs

1use super::{ClassWriter, CpEntry};
2use std::io::Write;
3
4impl<W: Write> ClassWriter<W> {
5    /// Adds a Utf8 constant to the constant pool
6    pub fn add_utf8(&mut self, s: String) -> u16 {
7        self.add_cp_entry(CpEntry::Utf8(s))
8    }
9
10    /// Adds a Class constant to the constant pool
11    pub fn add_class(&mut self, name: String) -> u16 {
12        let name_index = self.add_utf8(name);
13        self.add_cp_entry(CpEntry::Class(name_index))
14    }
15
16    /// Adds a String constant to the constant pool
17    pub fn add_string(&mut self, value: String) -> u16 {
18        let utf8_index = self.add_utf8(value);
19        self.add_cp_entry(CpEntry::String(utf8_index))
20    }
21
22    /// Adds a NameAndType constant to the constant pool
23    pub fn add_name_and_type(&mut self, name: String, descriptor: String) -> u16 {
24        let name_index = self.add_utf8(name);
25        let descriptor_index = self.add_utf8(descriptor);
26        self.add_cp_entry(CpEntry::NameAndType(name_index, descriptor_index))
27    }
28
29    /// Adds a Fieldref constant to the constant pool
30    pub fn add_field_ref(&mut self, class_name: String, name: String, descriptor: String) -> u16 {
31        let class_index = self.add_class(class_name);
32        let name_and_type_index = self.add_name_and_type(name, descriptor);
33        self.add_cp_entry(CpEntry::Fieldref(class_index, name_and_type_index))
34    }
35
36    /// Adds a Methodref constant to the constant pool
37    pub fn add_method_ref(&mut self, class_name: String, name: String, descriptor: String) -> u16 {
38        let class_index = self.add_class(class_name);
39        let name_and_type_index = self.add_name_and_type(name, descriptor);
40        self.add_cp_entry(CpEntry::Methodref(class_index, name_and_type_index))
41    }
42
43    /// Adds an InterfaceMethodref constant to the constant pool
44    pub fn add_interface_method_ref(&mut self, class_name: String, name: String, descriptor: String) -> u16 {
45        let class_index = self.add_class(class_name);
46        let name_and_type_index = self.add_name_and_type(name, descriptor);
47        self.add_cp_entry(CpEntry::InterfaceMethodref(class_index, name_and_type_index))
48    }
49
50    /// Adds an Integer constant to the constant pool
51    pub fn add_int(&mut self, val: i32) -> u16 {
52        self.add_cp_entry(CpEntry::Integer(val))
53    }
54
55    /// Adds a Float constant to the constant pool
56    pub fn add_float(&mut self, val: f32) -> u16 {
57        self.add_cp_entry(CpEntry::Float(val.to_bits()))
58    }
59
60    /// Adds a Long constant to the constant pool
61    pub fn add_long(&mut self, val: i64) -> u16 {
62        self.add_cp_entry(CpEntry::Long(val))
63    }
64
65    /// Adds a Double constant to the constant pool
66    pub fn add_double(&mut self, val: f64) -> u16 {
67        self.add_cp_entry(CpEntry::Double(val.to_bits()))
68    }
69
70    /// Adds a constant pool entry and returns its index
71    pub fn add_cp_entry(&mut self, entry: CpEntry) -> u16 {
72        if let Some(&index) = self.cp_map.get(&entry) {
73            return index;
74        }
75
76        let index = (self.cp_entries.len() + 1) as u16;
77        self.cp_entries.push(entry.clone());
78        self.cp_map.insert(entry, index);
79
80        // Long 和 Double 占用两个常量池槽位
81        match self.cp_entries.last().unwrap() {
82            CpEntry::Long(_) | CpEntry::Double(_) => {
83                // 占位符,不实际写入,但增加长度
84                self.cp_entries.push(CpEntry::Utf8("Padding".to_string()));
85            }
86            _ => {}
87        }
88
89        index
90    }
91
92    /// Writes the constant pool to the class file
93    pub fn write_constant_pool(&mut self) -> gaia_types::Result<()> {
94        // 写入常量池计数(+1 因为索引从1开始)
95        self.writer.write_u16((self.cp_entries.len() + 1) as u16)?;
96
97        // 写入常量池条目
98        let mut i = 0;
99        while i < self.cp_entries.len() {
100            let entry = &self.cp_entries[i];
101            match entry {
102                CpEntry::Utf8(s) => {
103                    self.writer.write_u8(1)?; // CONSTANT_Utf8 tag
104                    self.writer.write_u16(s.len() as u16)?;
105                    self.writer.write_all(s.as_bytes())?;
106                }
107                CpEntry::Class(name_idx) => {
108                    self.writer.write_u8(7)?; // CONSTANT_Class tag
109                    self.writer.write_u16(*name_idx)?;
110                }
111                CpEntry::String(utf8_idx) => {
112                    self.writer.write_u8(8)?; // CONSTANT_String tag
113                    self.writer.write_u16(*utf8_idx)?;
114                }
115                CpEntry::NameAndType(name_idx, desc_idx) => {
116                    self.writer.write_u8(12)?; // CONSTANT_NameAndType tag
117                    self.writer.write_u16(*name_idx)?;
118                    self.writer.write_u16(*desc_idx)?;
119                }
120                CpEntry::Fieldref(class_idx, nt_idx) => {
121                    self.writer.write_u8(9)?; // CONSTANT_Fieldref tag
122                    self.writer.write_u16(*class_idx)?;
123                    self.writer.write_u16(*nt_idx)?;
124                }
125                CpEntry::Methodref(class_idx, nt_idx) => {
126                    self.writer.write_u8(10)?; // CONSTANT_Methodref tag
127                    self.writer.write_u16(*class_idx)?;
128                    self.writer.write_u16(*nt_idx)?;
129                }
130                CpEntry::InterfaceMethodref(class_idx, nt_idx) => {
131                    self.writer.write_u8(11)?; // CONSTANT_InterfaceMethodref tag
132                    self.writer.write_u16(*class_idx)?;
133                    self.writer.write_u16(*nt_idx)?;
134                }
135                CpEntry::Integer(val) => {
136                    self.writer.write_u8(3)?; // CONSTANT_Integer tag
137                    self.writer.write_i32(*val)?;
138                }
139                CpEntry::Float(bits) => {
140                    self.writer.write_u8(4)?; // CONSTANT_Float tag
141                    self.writer.write_u32(*bits)?;
142                }
143                CpEntry::Long(val) => {
144                    self.writer.write_u8(5)?; // CONSTANT_Long tag
145                    self.writer.write_i64(*val)?;
146                    i += 1; // Long 占用两个槽位
147                }
148                CpEntry::Double(bits) => {
149                    self.writer.write_u8(6)?; // CONSTANT_Double tag
150                    self.writer.write_u64(*bits)?;
151                    i += 1; // Double 占用两个槽位
152                }
153            }
154            i += 1;
155        }
156
157        Ok(())
158    }
159}