lua_kit/
read.rs

1//! Deserialization code.
2
3use std::io::{self, Read};
4use std::mem::size_of;
5use byteorder::ReadBytesExt;
6use byteorder::NativeEndian as E;
7
8use super::{
9	SIGNATURE, FORMAT, VERSION, DATA, TEST_INT, TEST_NUMBER,
10	Int, Size, Instruction, Integer, Number,
11	Constant, Upvalue, LocalVar, Debug, Function,
12};
13
14/// Deserialize bytecode into a `Function`.
15pub fn read_file<R: Read>(read: R) -> io::Result<Function> {
16	let mut reader = Reader { out: read };
17	try!(reader.read_header());
18	try!(reader.out.read_u8()); // discard upvals header
19	reader.read_function()
20}
21
22struct Reader<R: Read> {
23	out: R,
24}
25
26fn invalid<T, S: Into<Box<::std::error::Error + Send + Sync>>>(s: S) -> io::Result<T> {
27	Err(io::Error::new(io::ErrorKind::InvalidInput, s))
28}
29
30macro_rules! check {
31	($get:expr, $want:expr, $note:expr) => {{
32		let get = $get;
33		let want = $want;
34		if get != want {
35			return Err(io::Error::new(io::ErrorKind::InvalidInput, format!(
36				"invalid {}, expected {:?} but got {:?}",
37				$note, want, get,
38			)));
39		}
40	}}
41}
42
43impl<R: Read> Reader<R> {
44	fn read_all(&mut self, mut buf: &mut [u8]) -> io::Result<()> {
45		let mut start = 0;
46		let len = buf.len();
47		while start < len {
48			let n = try!(self.out.read(&mut buf[start..]));
49			if n == 0 {
50				return invalid("unexpected EOF");
51			}
52			start += n;
53		}
54		Ok(())
55	}
56
57	fn read_header(&mut self) -> io::Result<()> {
58		let mut buffer = [0u8; 6];
59		try!(self.read_all(&mut buffer[..4]));
60		check!(&buffer[..4], SIGNATURE, "signature");
61		check!(try!(self.out.read_u8()), VERSION, "version");
62		check!(try!(self.out.read_u8()), FORMAT, "format");
63		try!(self.read_all(&mut buffer));
64		check!(&buffer, DATA, "test data");
65		check!(try!(self.out.read_u8()), size_of::<Int>() as u8, "sizeof(int)");
66		check!(try!(self.out.read_u8()), size_of::<Size>() as u8, "sizeof(size_t)");
67		check!(try!(self.out.read_u8()), size_of::<Instruction>() as u8, "sizeof(Instruction)");
68		check!(try!(self.out.read_u8()), size_of::<Integer>() as u8, "sizeof(Integer)");
69		check!(try!(self.out.read_u8()), size_of::<Number>() as u8, "sizeof(Number)");
70		check!(try!(self.out.read_i64::<E>()), TEST_INT, "test integer");
71		check!(try!(self.out.read_f64::<E>()), TEST_NUMBER, "test number");
72		Ok(())
73	}
74
75	fn read_function(&mut self) -> io::Result<Function> {
76		Ok(Function {
77			source: try!(self.read_string()),
78			line_start: try!(self.out.read_i32::<E>()),
79			line_end: try!(self.out.read_i32::<E>()),
80			num_params: try!(self.out.read_u8()),
81			is_vararg: try!(self.out.read_u8()) != 0,
82			max_stack_size: try!(self.out.read_u8()),
83			code: try!(self.read_vec(|this| Ok(try!(this.out.read_u32::<E>())))),
84			constants: try!(self.read_vec(|this| Ok(match try!(this.out.read_u8()) {
85				0x00 => Constant::Nil,
86				0x01 => Constant::Boolean(try!(this.out.read_u8()) != 0),
87				0x03 => Constant::Float(try!(this.out.read_f64::<E>())),
88				0x13 => Constant::Int(try!(this.out.read_i64::<E>())),
89				0x04 => Constant::ShortString(try!(this.read_string())),
90				0x14 => Constant::LongString(try!(this.read_string())),
91				o => return invalid(format!("unknown constant type {}", o)),
92			}))),
93			upvalues: try!(self.read_vec(|this| {
94				let stack = try!(this.out.read_u8());
95				let idx = try!(this.out.read_u8());
96				Ok(match stack {
97					0 => Upvalue::Outer(idx),
98					_ => Upvalue::Stack(idx),
99				})
100			})),
101			protos: try!(self.read_vec(|this| this.read_function())),
102			debug: Debug {
103				lineinfo: try!(self.read_vec(|this| Ok(try!(this.out.read_i32::<E>())))),
104				localvars: try!(self.read_vec(|this| Ok(LocalVar {
105					name: try!(this.read_string()),
106					start_pc: try!(this.out.read_i32::<E>()),
107					end_pc: try!(this.out.read_i32::<E>()),
108				}))),
109				upvalues: try!(self.read_vec(|this| this.read_string())),
110			},
111		})
112	}
113
114	#[inline]
115	fn read_vec<F, T>(&mut self, f: F) -> io::Result<Vec<T>>
116		where F: Fn(&mut Self) -> io::Result<T>
117	{
118		let len = try!(self.out.read_u32::<E>());
119		(0..len).map(|_| f(self)).collect()
120	}
121
122	fn read_string(&mut self) -> io::Result<String> {
123		let first = try!(self.out.read_u8());
124		if first == 0 {
125			Ok(String::new())
126		} else {
127			let len = if first < 0xff {
128				first as usize
129			} else {
130				try!(self.out.read_u32::<E>()) as usize
131			} - 1;
132			let mut buffer = vec![0u8; len];
133			try!(self.read_all(&mut buffer));
134			// TODO: May need to return a Vec<u8> rather than String
135			match String::from_utf8(buffer) {
136				Ok(s) => Ok(s),
137				Err(_) => invalid("not utf8"),
138			}
139		}
140	}
141}