Skip to content

Commit f487873

Browse files
committed
update: add writer for chunk
Signed-off-by: yjhmelody <[email protected]>
1 parent 62e3cda commit f487873

File tree

6 files changed

+279
-16
lines changed

6 files changed

+279
-16
lines changed

src/binary/chunk.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub const LUAC_FORMAT: u8 = 0;
1010
/// "\x19\x93\r\n\x1a\n"
1111
pub const LUAC_DATA: [u8; 6] = [0x19, 0x93, 0x0d, 0x0a, 0x1a, 0x0a];
1212
pub const CINT_SIZE: u8 = 4;
13-
pub const CSIZET_SIZE: u8 = 8;
13+
pub const CSIZET_SIZE: u8 = 4;
1414
pub const INSTRUCTION_SIZE: u8 = 4;
1515
pub const LUA_INTEGER_SIZE: u8 = 8;
1616
pub const LUA_NUMBER_SIZE: u8 = 8;

src/binary/mod.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::rc::Rc;
22

33
pub mod chunk;
4-
mod reader;
4+
pub mod reader;
5+
pub mod writer;
56

67
/// decode Lua binary chunk to prototype structure
78
pub fn decode(data: Vec<u8>) -> Rc<chunk::Prototype> {
@@ -10,3 +11,47 @@ pub fn decode(data: Vec<u8>) -> Rc<chunk::Prototype> {
1011
r.read_byte();
1112
r.read_proto()
1213
}
14+
15+
pub fn encode(proto: Rc<chunk::Prototype>) -> Vec<u8> {
16+
let mut writer = writer::Writer::new();
17+
writer.write_header();
18+
writer.write_byte(4);
19+
writer.write_proto(proto);
20+
writer.as_bytes()
21+
}
22+
23+
mod tests {
24+
use std::fs;
25+
26+
use super::*;
27+
28+
#[test]
29+
fn test_header() {
30+
let mut writer = writer::Writer::new();
31+
writer.write_header();
32+
let mut reader = reader::Reader::new(writer.as_bytes());
33+
reader.check_header();
34+
assert_eq!(1, 0);
35+
}
36+
37+
38+
#[test]
39+
fn test_decode() {
40+
let s = fs::read("D:/code/Rust/lua-rs/tests/luac.out").expect("error");
41+
let proto = decode(s);
42+
43+
println!("{:#?}", proto);
44+
assert_eq!(1, 0);
45+
}
46+
47+
#[test]
48+
fn test_encode() {
49+
let s = fs::read("D:/code/Rust/lua-rs/tests/luac.out").expect("error");
50+
let proto = encode(decode(s));
51+
// println!("{:#?}", proto);
52+
53+
let s = unsafe { String::from_utf8_unchecked(proto) };
54+
fs::write("D:/code/Rust/lua-rs/tests/test.out", s);
55+
assert_eq!(2, 0);
56+
}
57+
}

src/binary/reader.rs

+11
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@ pub struct Reader {
99
}
1010

1111
impl Reader {
12+
#[inline]
1213
pub fn new(data: Vec<u8>) -> Self {
1314
Self { data, pos: 0 }
1415
}
1516

17+
#[inline]
1618
pub fn read_byte(&mut self) -> u8 {
1719
let b = self.data[self.pos];
1820
self.pos += 1;
1921
b
2022
}
2123

24+
#[inline]
2225
fn read_u32(&mut self) -> u32 {
2326
let a0 = self.read_byte() as u32;
2427
let a1 = self.read_byte() as u32;
@@ -27,16 +30,20 @@ impl Reader {
2730
(a3 << 24) | (a2 << 16) | (a1 << 8) | a0
2831
}
2932

33+
#[inline]
3034
fn read_u64(&mut self) -> u64 {
3135
let a0 = self.read_u32() as u64;
3236
let a1 = self.read_u32() as u64;
37+
dbg!(a1 << 32 | a0);
3338
(a1 << 32) | a0
3439
}
3540

41+
#[inline]
3642
fn read_lua_integer(&mut self) -> i64 {
3743
self.read_u64() as i64
3844
}
3945

46+
#[inline]
4047
fn read_lua_number(&mut self) -> f64 {
4148
use std::f64; // TODO
4249
f64::from_bits(self.read_u64())
@@ -50,6 +57,7 @@ impl Reader {
5057
vec
5158
}
5259

60+
#[inline]
5361
fn read_string(&mut self) -> String {
5462
self.read_string0().unwrap_or_default()
5563
}
@@ -93,6 +101,7 @@ impl Reader {
93101
assert_eq!(self.read_lua_number(), LUAC_NUM, "float format mismatch!");
94102
}
95103

104+
#[inline]
96105
pub fn read_proto(&mut self) -> Rc<Prototype> {
97106
self.read_proto0(None)
98107
}
@@ -129,13 +138,15 @@ impl Reader {
129138
}
130139
}
131140

141+
#[inline]
132142
fn read_up_value(&mut self) -> UpValue {
133143
UpValue {
134144
instack: self.read_byte(),
135145
idx: self.read_byte(),
136146
}
137147
}
138148

149+
#[inline]
139150
fn read_loc_var(&mut self) -> LocalVar {
140151
LocalVar {
141152
var_name: self.read_string(),

src/binary/writer.rs

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
use std::rc::Rc;
2+
3+
use crate::binary::chunk::*;
4+
5+
#[derive(Debug, Clone)]
6+
pub struct Writer {
7+
data: Vec<u8>,
8+
}
9+
10+
impl Writer {
11+
#[inline]
12+
pub fn new() -> Self {
13+
Self { data: Vec::with_capacity(1024) }
14+
}
15+
16+
#[inline]
17+
pub fn write_byte(&mut self, b: u8) {
18+
self.data.push(b);
19+
}
20+
21+
#[inline]
22+
pub fn as_bytes(self) -> Vec<u8> {
23+
self.data
24+
}
25+
26+
fn write_u32(&mut self, b4: u32) {
27+
let a0 = (b4 >> 24) as u8;
28+
let a1 = (b4 >> 16) as u8;
29+
let a2 = (b4 >> 8) as u8;
30+
let a3 = b4 as u8;
31+
self.write_byte(a3);
32+
self.write_byte(a2);
33+
self.write_byte(a1);
34+
self.write_byte(a0);
35+
}
36+
37+
#[inline]
38+
fn write_u64(&mut self, b8: u64) {
39+
dbg!(&b8);
40+
let a0 = ((b8 & 0xFF_FF_FF_FF_00_00_00_00) >> 32) as u32;
41+
let a1 = (b8 & 0xFF_FF_FF_FF) as u32;
42+
43+
self.write_u32(a1);
44+
self.write_u32(a0);
45+
}
46+
47+
#[inline]
48+
fn write_lua_integer(&mut self, i: i64) {
49+
self.write_u64(i as u64);
50+
}
51+
52+
#[inline]
53+
fn write_lua_number(&mut self, n: f64) {
54+
self.write_u64(n.to_bits());
55+
}
56+
57+
#[inline]
58+
fn write_bytes(&mut self, bytes: Vec<u8>) {
59+
for b in bytes {
60+
self.write_byte(b);
61+
}
62+
}
63+
64+
#[inline]
65+
fn write_string(&mut self, s: &String) {
66+
self.write_string0(s).unwrap_or_default()
67+
}
68+
69+
fn write_string0(&mut self, s: &String) -> Option<()> {
70+
if s.len() == 0 {
71+
None
72+
} else if s.len() < 0xFF {
73+
self.write_byte(s.len() as u8 - 1);
74+
self.write_bytes(s.as_bytes().to_vec());
75+
Some(())
76+
} else {
77+
// todo
78+
unimplemented!()
79+
}
80+
}
81+
82+
pub fn write_header(&mut self) {
83+
self.write_bytes(LUA_SIGNATURE.to_vec());
84+
self.write_byte(LUAC_VERSION);
85+
self.write_byte(LUAC_FORMAT);
86+
self.write_bytes(LUAC_DATA.to_vec());
87+
self.write_byte(CINT_SIZE);
88+
self.write_byte(CSIZET_SIZE);
89+
self.write_byte(INSTRUCTION_SIZE);
90+
self.write_byte(LUA_INTEGER_SIZE);
91+
self.write_byte(LUA_NUMBER_SIZE);
92+
self.write_lua_integer(LUAC_INT);
93+
self.write_lua_number(LUAC_NUM);
94+
}
95+
96+
pub fn write_proto(&mut self, proto: Rc<Prototype>) {
97+
self.write_string0(&proto.source.clone().unwrap());
98+
self.write_u32(proto.line_defined);
99+
self.write_u32(proto.last_line_defined);
100+
self.write_byte(proto.num_params);
101+
self.write_byte(proto.is_vararg);
102+
self.write_byte(proto.max_stack_size);
103+
104+
self.write_u32(proto.code.len() as u32);
105+
for ins in proto.code.iter() {
106+
self.write_u32(*ins);
107+
}
108+
109+
self.write_u32(proto.constants.len() as u32);
110+
for cst in proto.constants.iter() {
111+
self.write_constant(cst);
112+
}
113+
114+
self.write_u32(proto.up_values.len() as u32);
115+
for up_val in proto.up_values.iter() {
116+
self.write_up_value(up_val);
117+
}
118+
119+
self.write_u32(proto.prototypes.len() as u32);
120+
for prototype in proto.prototypes.iter() {
121+
self.write_proto(prototype.clone());
122+
}
123+
124+
self.write_u32(proto.line_info.len() as u32);
125+
for line in proto.line_info.iter() {
126+
self.write_u32(*line);
127+
}
128+
129+
self.write_u32(proto.local_vars.len() as u32);
130+
for local_var in proto.local_vars.iter() {
131+
self.write_loc_var(local_var);
132+
}
133+
134+
self.write_u32(proto.up_value_names.len() as u32);
135+
for name in proto.up_value_names.iter() {
136+
self.write_string(name);
137+
}
138+
}
139+
140+
fn write_constant(&mut self, cst: &Constant) {
141+
match cst {
142+
Constant::Nil => { self.write_byte(TAG_NIL) }
143+
Constant::Boolean(b) => {
144+
self.write_byte(TAG_BOOLEAN);
145+
self.write_byte(*b as u8);
146+
}
147+
Constant::Integer(i) => {
148+
self.write_byte(TAG_INTEGER);
149+
self.write_lua_integer(*i);
150+
}
151+
Constant::Number(n) => {
152+
self.write_byte(TAG_NUMBER);
153+
self.write_lua_number(*n);
154+
}
155+
Constant::String(s) => {
156+
if s.len() >= 255 {
157+
self.write_byte(TAG_LONG_STR);
158+
} else {
159+
self.write_byte(TAG_SHORT_STR);
160+
}
161+
self.write_string(s);
162+
}
163+
};
164+
}
165+
166+
167+
#[inline]
168+
fn write_up_value(&mut self, upval: &UpValue) {
169+
self.write_byte(upval.instack);
170+
self.write_byte(upval.idx);
171+
}
172+
173+
#[inline]
174+
fn write_loc_var(&mut self, local_var: &LocalVar) {
175+
self.write_string(&local_var.var_name);
176+
self.write_u32(local_var.start_pc);
177+
self.write_u32(local_var.end_pc);
178+
}
179+
}

0 commit comments

Comments
 (0)