jbcrs_basic/writer/
mod.rs

1mod encode;
2
3use result::*;
4use super::constpool::*;
5use super::tree::*;
6use self::encode::Encoder;
7
8/// Writes a constant pool and class to a byte vector
9pub fn write(constant_pool: &Pool, class: &Class) -> Result<Vec<u8>> {
10    let mut encoder = Encoder::new();
11
12    // write magic and version
13    encoder.write_bytes(MAGIC);
14    encoder.write_u16(class.minor_version);
15    encoder.write_u16(class.major_version);
16
17    write_constant_pool(&mut encoder, constant_pool);
18
19    encoder.write_u16(class.access_flags.bits());
20    encoder.write_u16(class.name);
21    encoder.write_u16(class.super_name);
22
23    encoder.write_u16(class.interfaces.len() as u16);
24    for interface in &class.interfaces {
25        encoder.write_u16(*interface);
26    }
27
28    write_fields(&mut encoder, &class.fields);
29    write_methods(&mut encoder, &class.methods);
30
31    write_attributes(&mut encoder, &class.attributes);
32
33    Ok(encoder.bytes())
34}
35
36/// Writes the constant pool
37fn write_constant_pool(encoder: &mut Encoder, pool: &Pool) {
38    // write length and after that the items
39    encoder.write_u16(pool.len());
40    for (_index, item) in pool.iter() {
41        match *item {
42            Item::UTF8(ref s) => {
43                encoder.write_u8(1);
44                encoder.write_u16(s.len() as u16);
45                encoder.write_str(s.as_ref());
46            }
47            Item::Integer(value) => {
48                encoder.write_u8(3);
49                encoder.write_i32(value);
50            }
51            Item::Float(value) => {
52                encoder.write_u8(4);
53                encoder.write_f32(value);
54            }
55            Item::Long(value) => {
56                encoder.write_u8(5);
57                encoder.write_i64(value);
58            }
59            Item::Double(value) => {
60                encoder.write_u8(6);
61                encoder.write_f64(value);
62            }
63            Item::Class(class) => {
64                encoder.write_u8(7);
65                encoder.write_u16(class);
66            }
67            Item::String(class) => {
68                encoder.write_u8(8);
69                encoder.write_u16(class);
70            }
71            Item::FieldRef {
72                class,
73                name_and_type,
74            } => {
75                encoder.write_u8(9);
76                encoder.write_u16(class);
77                encoder.write_u16(name_and_type);
78            }
79            Item::MethodRef {
80                class,
81                name_and_type,
82            } => {
83                encoder.write_u8(10);
84                encoder.write_u16(class);
85                encoder.write_u16(name_and_type);
86            }
87            Item::InterfaceMethodRef {
88                class,
89                name_and_type,
90            } => {
91                encoder.write_u8(11);
92                encoder.write_u16(class);
93                encoder.write_u16(name_and_type);
94            }
95            Item::NameAndType { name, desc } => {
96                encoder.write_u8(12);
97                encoder.write_u16(name);
98                encoder.write_u16(desc);
99            }
100            Item::MethodHandle { ref kind, index } => {
101                use self::ReferenceKind::*;
102
103                encoder.write_u8(15);
104                encoder.write_u8(match *kind {
105                    GetField => 1,
106                    GetStatic => 2,
107                    PutField => 3,
108                    PutStatic => 4,
109                    InvokeVirtual => 5,
110                    InvokeStatic => 6,
111                    InvokeSpecial => 7,
112                    NewInvokeSpecial => 8,
113                    InvokeInterface => 9,
114                });
115                encoder.write_u16(index);
116            }
117            Item::MethodType(index) => {
118                encoder.write_u8(16);
119                encoder.write_u16(index);
120            }
121            Item::InvokeDynamic {
122                bootstrap_method,
123                name_and_type,
124            } => {
125                encoder.write_u8(18);
126                encoder.write_u16(bootstrap_method);
127                encoder.write_u16(name_and_type);
128            }
129            Item::Module(index) => {
130                encoder.write_u8(19);
131                encoder.write_u16(index);
132            }
133            Item::Package(index) => {
134                encoder.write_u8(20);
135                encoder.write_u16(index);
136            }
137        }
138    }
139}
140
141/// Writes all fields to the encoder
142fn write_fields(encoder: &mut Encoder, fields: &[Field]) {
143    encoder.write_u16(fields.len() as u16);
144    for field in fields {
145        encoder.write_u16(field.access_flags.bits());
146        encoder.write_u16(field.name);
147        encoder.write_u16(field.desc);
148        write_attributes(encoder, &field.attributes);
149    }
150}
151
152/// Writes all methods to the encoder
153fn write_methods(encoder: &mut Encoder, methods: &[Method]) {
154    encoder.write_u16(methods.len() as u16);
155    for method in methods {
156        encoder.write_u16(method.access_flags.bits());
157        encoder.write_u16(method.name);
158        encoder.write_u16(method.desc);
159        write_attributes(encoder, &method.attributes);
160    }
161}
162
163/// Writes all attributes to the encoder
164fn write_attributes(encoder: &mut Encoder, _attributes: &[Attribute]) {
165    // implement later
166    encoder.write_u16(0);
167}