1
- use std:: io ;
1
+ use std:: { convert :: TryInto , io } ;
2
2
3
3
use bytecode:: * ;
4
- use :: { parsing, ConstantPoolIndex } ;
4
+
5
+ use crate :: ClassFile ;
6
+ use { parsing, ConstantPoolIndex } ;
5
7
6
8
const EXCEPTION_ENTRY_LENGTH : usize = 8 ;
7
9
8
- #[ derive( Debug ) ]
9
- #[ derive( Eq ) ]
10
- #[ derive( PartialEq ) ]
10
+ #[ derive( Debug , Eq , PartialEq , Clone ) ]
11
11
pub struct Attribute {
12
12
pub attribute_name_index : ConstantPoolIndex ,
13
13
pub info : Vec < u8 > ,
14
14
}
15
15
16
- #[ derive( Debug ) ]
17
- #[ derive( PartialEq ) ]
16
+ #[ derive( Debug , Eq , PartialEq , Clone ) ]
17
+ pub struct AttributeSet {
18
+ pub attributes : Vec < Attribute > ,
19
+ }
20
+
21
+ impl AttributeSet {
22
+ /// Find an attribute with the specified name
23
+ pub fn find_attribute < T : AsRef < str > > (
24
+ & self ,
25
+ class_file : & ClassFile ,
26
+ attribute_name : T ,
27
+ ) -> Option < & Attribute > {
28
+ // we can index this more efficiently
29
+ self . attributes . iter ( ) . find ( |attr| {
30
+ class_file. get_constant_utf8 ( attr. attribute_name_index ) == attribute_name. as_ref ( )
31
+ } )
32
+ }
33
+
34
+ pub fn get_signature ( & self , class_file : & ClassFile ) -> Option < String > {
35
+ self . find_attribute ( class_file, "Signature" ) . map ( |attr| {
36
+ // why is this such a PITA
37
+ let boxed_slice = attr. info . clone ( ) . into_boxed_slice ( ) ;
38
+ let boxed_array: Box < [ u8 ; 2 ] > = match boxed_slice. try_into ( ) {
39
+ Ok ( ba) => ba,
40
+ Err ( o) => panic ! ( "Expected a Vec of length {} but it was {}" , 2 , o. len( ) ) ,
41
+ } ;
42
+ let index = u16:: from_be_bytes ( * boxed_array) ;
43
+
44
+ class_file. get_constant_utf8 ( index as usize ) . to_string ( )
45
+ } )
46
+ }
47
+ }
48
+
49
+ #[ derive( Debug , PartialEq ) ]
18
50
pub struct Code {
19
51
pub max_stack : u16 ,
20
52
pub max_locals : u16 ,
21
53
pub code : Vec < ( usize , Bytecode ) > ,
22
54
pub exception_table : Vec < ExceptionTableEntry > ,
23
- pub attributes : Vec < Attribute > ,
55
+ pub attributes : AttributeSet ,
24
56
}
25
57
26
58
impl Code {
27
59
pub fn from_bytes ( bytes : & [ u8 ] ) -> io:: Result < Code > {
28
60
let max_stack = u16:: from_be_bytes ( [ bytes[ 0 ] , bytes[ 1 ] ] ) ;
29
61
let max_locals = u16:: from_be_bytes ( [ bytes[ 2 ] , bytes[ 3 ] ] ) ;
30
62
31
- let code_length = u32:: from_be_bytes (
32
- [ bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] , bytes[ 7 ] ]
33
- ) as usize ;
63
+ let code_length = u32:: from_be_bytes ( [ bytes[ 4 ] , bytes[ 5 ] , bytes[ 6 ] , bytes[ 7 ] ] ) as usize ;
34
64
35
65
let code_start = 8 ;
36
66
let code_end = code_start + code_length;
37
67
let code_bytes = & bytes[ code_start..code_end] ;
38
68
39
69
let code = Bytecode :: from_bytes ( code_bytes) ;
40
70
41
- let exception_table_length = u16:: from_be_bytes (
42
- [ bytes[ code_end] , bytes[ code_end + 1 ] ]
43
- ) as usize ;
71
+ let exception_table_length =
72
+ u16:: from_be_bytes ( [ bytes[ code_end] , bytes[ code_end + 1 ] ] ) as usize ;
44
73
45
74
let mut exception_table = Vec :: with_capacity ( exception_table_length) ;
46
75
for i in 0 ..exception_table_length {
47
76
let entry_start = ( code_end + 2 ) + i * EXCEPTION_ENTRY_LENGTH ;
48
77
let entry_end = entry_start + EXCEPTION_ENTRY_LENGTH ;
49
78
50
- let entry = ExceptionTableEntry :: from_bytes (
51
- & bytes[ entry_start..entry_end]
52
- ) ;
79
+ let entry = ExceptionTableEntry :: from_bytes ( & bytes[ entry_start..entry_end] ) ;
53
80
54
81
exception_table. push ( entry) ;
55
82
}
56
83
57
- let attributes_start = ( code_end + 2 ) +
58
- exception_table_length * EXCEPTION_ENTRY_LENGTH ;
84
+ let attributes_start = ( code_end + 2 ) + exception_table_length * EXCEPTION_ENTRY_LENGTH ;
59
85
60
86
let mut attribute_bytes = & bytes[ attributes_start..] ;
61
87
let attributes = parsing:: read_attributes ( & mut attribute_bytes) ?;
@@ -70,8 +96,7 @@ impl Code {
70
96
}
71
97
}
72
98
73
- #[ derive( Debug ) ]
74
- #[ derive( PartialEq ) ]
99
+ #[ derive( Debug , PartialEq ) ]
75
100
pub struct ExceptionTableEntry {
76
101
pub start_pc : u16 ,
77
102
pub end_pc : u16 ,
0 commit comments