Skip to main content

jvm_assembler/program/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// JVM version information
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5pub struct JvmVersion {
6    /// Major version number
7    pub major: u16,
8    /// Minor version number
9    pub minor: u16,
10}
11
12impl JvmVersion {
13    /// Creates a new JVM version
14    pub fn new(major: u16, minor: u16) -> Self {
15        Self { major, minor }
16    }
17
18    /// Java 8 (version 52.0)
19    pub fn java_8() -> Self {
20        Self::new(52, 0)
21    }
22
23    /// Java 11 (version 55.0)
24    pub fn java_11() -> Self {
25        Self::new(55, 0)
26    }
27
28    /// Java 17 (version 61.0)
29    pub fn java_17() -> Self {
30        Self::new(61, 0)
31    }
32
33    /// Java 21 (version 65.0)
34    pub fn java_21() -> Self {
35        Self::new(65, 0)
36    }
37}
38
39/// JVM access flags
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
41pub struct JvmAccessFlags {
42    /// public access
43    pub is_public: bool,
44    /// private access
45    pub is_private: bool,
46    /// protected access
47    pub is_protected: bool,
48    /// static member
49    pub is_static: bool,
50    /// final member
51    pub is_final: bool,
52    /// synchronized method
53    pub is_synchronized: bool,
54    /// volatile field
55    pub is_volatile: bool,
56    /// transient field
57    pub is_transient: bool,
58    /// native method
59    pub is_native: bool,
60    /// interface type
61    pub is_interface: bool,
62    /// abstract member
63    pub is_abstract: bool,
64    /// strictfp method
65    pub is_strict: bool,
66    /// synthetic member
67    pub is_synthetic: bool,
68    /// annotation type
69    pub is_annotation: bool,
70    /// enum type
71    pub is_enum: bool,
72    /// module type
73    pub is_module: bool,
74}
75
76impl JvmAccessFlags {
77    /// Creates a new empty access flags
78    pub fn new() -> Self {
79        Self::default()
80    }
81
82    /// Creates access flags with public set to true
83    pub fn public() -> Self {
84        let mut flags = Self::new();
85        flags.is_public = true;
86        flags
87    }
88
89    /// Creates access flags with private set to true
90    pub fn private() -> Self {
91        let mut flags = Self::new();
92        flags.is_private = true;
93        flags
94    }
95
96    /// Converts to JVM bytecode access flags value
97    pub fn to_flags(&self) -> u16 {
98        let mut flags = 0u16;
99
100        if self.is_public {
101            flags |= 0x0001;
102        }
103        if self.is_private {
104            flags |= 0x0002;
105        }
106        if self.is_protected {
107            flags |= 0x0004;
108        }
109        if self.is_static {
110            flags |= 0x0008;
111        }
112        if self.is_final {
113            flags |= 0x0010;
114        }
115        if self.is_synchronized {
116            flags |= 0x0020;
117        }
118        if self.is_volatile {
119            flags |= 0x0040;
120        }
121        if self.is_transient {
122            flags |= 0x0080;
123        }
124        if self.is_native {
125            flags |= 0x0100;
126        }
127        if self.is_interface {
128            flags |= 0x0200;
129        }
130        if self.is_abstract {
131            flags |= 0x0400;
132        }
133        if self.is_strict {
134            flags |= 0x0800;
135        }
136        if self.is_synthetic {
137            flags |= 0x1000;
138        }
139        if self.is_annotation {
140            flags |= 0x2000;
141        }
142        if self.is_enum {
143            flags |= 0x4000;
144        }
145        if self.is_module {
146            flags |= 0x8000;
147        }
148
149        flags
150    }
151
152    /// Creates JvmAccessFlags from bytecode access flags value
153    pub fn from_flags(flags: u16) -> Self {
154        Self {
155            is_public: (flags & 0x0001) != 0,
156            is_private: (flags & 0x0002) != 0,
157            is_protected: (flags & 0x0004) != 0,
158            is_static: (flags & 0x0008) != 0,
159            is_final: (flags & 0x0010) != 0,
160            is_synchronized: (flags & 0x0020) != 0,
161            is_volatile: (flags & 0x0040) != 0,
162            is_transient: (flags & 0x0080) != 0,
163            is_native: (flags & 0x0100) != 0,
164            is_interface: (flags & 0x0200) != 0,
165            is_abstract: (flags & 0x0400) != 0,
166            is_strict: (flags & 0x0800) != 0,
167            is_synthetic: (flags & 0x1000) != 0,
168            is_annotation: (flags & 0x2000) != 0,
169            is_enum: (flags & 0x4000) != 0,
170            is_module: (flags & 0x8000) != 0,
171        }
172    }
173
174    /// Converts access flags to a vector of string modifiers
175    pub fn to_modifiers(&self) -> Vec<String> {
176        let mut modifiers = Vec::new();
177        if self.is_public {
178            modifiers.push("public".to_string());
179        }
180        if self.is_private {
181            modifiers.push("private".to_string());
182        }
183        if self.is_protected {
184            modifiers.push("protected".to_string());
185        }
186        if self.is_static {
187            modifiers.push("static".to_string());
188        }
189        if self.is_final {
190            modifiers.push("final".to_string());
191        }
192        if self.is_synchronized {
193            modifiers.push("synchronized".to_string());
194        }
195        if self.is_volatile {
196            modifiers.push("volatile".to_string());
197        }
198        if self.is_transient {
199            modifiers.push("transient".to_string());
200        }
201        if self.is_native {
202            modifiers.push("native".to_string());
203        }
204        if self.is_interface {
205            modifiers.push("interface".to_string());
206        }
207        if self.is_abstract {
208            modifiers.push("abstract".to_string());
209        }
210        if self.is_strict {
211            modifiers.push("strictfp".to_string());
212        }
213        if self.is_synthetic {
214            modifiers.push("synthetic".to_string());
215        }
216        if self.is_annotation {
217            modifiers.push("annotation".to_string());
218        }
219        if self.is_enum {
220            modifiers.push("enum".to_string());
221        }
222        if self.is_module {
223            modifiers.push("module".to_string());
224        }
225        modifiers
226    }
227}
228
229/// JVM attribute
230#[derive(Debug, Clone)]
231pub enum JvmAttribute {
232    /// Source file name
233    SourceFile {
234        /// File name
235        filename: String,
236    },
237    /// Constant value for a field
238    ConstantValue {
239        /// The constant value entry in the pool
240        value: super::pool::JvmConstantPoolEntry,
241    },
242    /// Method code
243    Code {
244        /// Maximum stack size
245        max_stack: u16,
246        /// Maximum local variables
247        max_locals: u16,
248        /// List of instructions
249        instructions: Vec<super::instructions::JvmInstruction>,
250        /// Exception handler table
251        exception_table: Vec<super::entities::JvmExceptionHandler>,
252        /// Code attributes
253        attributes: Vec<JvmAttribute>,
254    },
255    /// Stack map table for verification
256    StackMapTable {
257        /// Stack map frames
258        frames: Vec<JvmStackMapFrame>,
259    },
260    /// Exceptions thrown by a method
261    Exceptions {
262        /// List of exception class names
263        exceptions: Vec<String>,
264    },
265    /// Inner classes information
266    InnerClasses {
267        /// List of inner classes
268        classes: Vec<JvmInnerClass>,
269    },
270    /// Enclosing method of a local or anonymous class
271    EnclosingMethod {
272        /// Class name
273        class_name: String,
274        /// Method name
275        method_name: Option<String>,
276        /// Method descriptor
277        method_descriptor: Option<String>,
278    },
279    /// Generic signature
280    Signature {
281        /// Signature string
282        signature: String,
283    },
284    /// Line number table for debugging
285    LineNumberTable {
286        /// Line number entries
287        entries: Vec<JvmLineNumberEntry>,
288    },
289    /// Local variable table for debugging
290    LocalVariableTable {
291        /// Local variable entries
292        entries: Vec<JvmLocalVariableEntry>,
293    },
294    /// Unknown attribute
295    Unknown {
296        /// Attribute name
297        name: String,
298        /// Raw attribute data
299        data: Vec<u8>,
300    },
301}
302
303/// JVM inner class information
304#[derive(Debug, Clone)]
305pub struct JvmInnerClass {
306    /// Inner class name
307    pub inner_class: String,
308    /// Outer class name
309    pub outer_class: Option<String>,
310    /// Inner name
311    pub inner_name: Option<String>,
312    /// Access flags
313    pub access_flags: JvmAccessFlags,
314}
315
316/// JVM line number table entry
317#[derive(Debug, Clone)]
318pub struct JvmLineNumberEntry {
319    /// Starting PC
320    pub start_pc: u16,
321    /// Line number
322    pub line_number: u16,
323}
324
325/// JVM local variable table entry
326#[derive(Debug, Clone)]
327pub struct JvmLocalVariableEntry {
328    /// Starting PC
329    pub start_pc: u16,
330    /// Length of the range
331    pub length: u16,
332    /// Variable name
333    pub name: String,
334    /// Variable descriptor
335    pub descriptor: String,
336    /// Local variable index
337    pub index: u16,
338}
339
340/// JVM verification type (used in StackMapTable)
341#[derive(Debug, Clone, PartialEq, Eq, Hash)]
342pub enum JvmVerificationType {
343    /// Top type
344    Top,
345    /// Integer type
346    Integer,
347    /// Float type
348    Float,
349    /// Double type
350    Double,
351    /// Long type
352    Long,
353    /// Null type
354    Null,
355    /// Uninitialized this
356    UninitializedThis,
357    /// Object type with class name
358    Object {
359        /// Class name
360        class_name: String,
361    },
362    /// Uninitialized object at given offset
363    Uninitialized {
364        /// Bytecode offset
365        offset: u16,
366    },
367}
368
369/// JVM stack map frame
370#[derive(Debug, Clone)]
371pub enum JvmStackMapFrame {
372    /// Same frame
373    Same {
374        /// Offset delta
375        offset_delta: u16,
376    },
377    /// Same frame with 1 stack item
378    SameLocals1StackItem {
379        /// Offset delta
380        offset_delta: u16,
381        /// Stack item verification type
382        stack: JvmVerificationType,
383    },
384    /// Same frame with 1 stack item (extended offset)
385    SameLocals1StackItemExtended {
386        /// Offset delta
387        offset_delta: u16,
388        /// Stack item verification type
389        stack: JvmVerificationType,
390    },
391    /// Chop frame
392    Chop {
393        /// Offset delta
394        offset_delta: u16,
395        /// Number of locals to chop
396        k: u8,
397    },
398    /// Same frame (extended offset)
399    SameExtended {
400        /// Offset delta
401        offset_delta: u16,
402    },
403    /// Append frame
404    Append {
405        /// Offset delta
406        offset_delta: u16,
407        /// New locals
408        locals: Vec<JvmVerificationType>,
409    },
410    /// Full frame
411    Full {
412        /// Offset delta
413        offset_delta: u16,
414        /// All locals
415        locals: Vec<JvmVerificationType>,
416        /// All stack items
417        stack: Vec<JvmVerificationType>,
418    },
419}
420
421/// JVM field information
422#[derive(Debug, Clone)]
423pub struct JvmField {
424    /// Field name
425    pub name: String,
426    /// Field descriptor
427    pub descriptor: String,
428    /// Access flags
429    pub access_flags: JvmAccessFlags,
430    /// Field attributes
431    pub attributes: Vec<JvmAttribute>,
432    /// Constant value for the field (if any)
433    pub constant_value: Option<super::pool::JvmConstantPoolEntry>,
434}
435
436impl JvmField {
437    /// Creates a new JVM field
438    pub fn new(name: String, descriptor: String) -> Self {
439        Self {
440            name,
441            descriptor,
442            access_flags: JvmAccessFlags::new(),
443            attributes: Vec::new(),
444            constant_value: None,
445        }
446    }
447}