]> Witch of Git - jade-rose/blob - toolchain/src/lib.rs
Upgrade spec to v0.2.1
[jade-rose] / toolchain / src / lib.rs
1 pub mod inst;
2 #[cfg(target_arch = "wasm32")]
3 pub mod js;
4
5 use inst::Decode;
6 pub use inst::Inst;
7 use std::io::{self, Read};
8
9 pub enum Error {
10 Io { position: usize, error: io::Error },
11 }
12
13 pub fn disassemble(reader: &mut impl io::Read) -> Result<Vec<Inst>, Error> {
14 let mut results = Vec::new();
15 let mut reader = PositionedRead::new(reader);
16 loop {
17 let position = reader.position;
18 match Inst::decode(&mut reader) {
19 Ok(inst) => results.push(inst),
20 Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => break,
21 Err(err) => {
22 return Err(Error::Io {
23 position,
24 error: err,
25 })
26 }
27 }
28 }
29 Ok(results)
30 }
31
32 struct PositionedRead<'a, R> {
33 inner: &'a mut R,
34 position: usize,
35 }
36
37 impl<'a, R> PositionedRead<'a, R> {
38 pub fn new(inner: &'a mut R) -> Self {
39 PositionedRead { inner, position: 0 }
40 }
41 }
42
43 impl<'a, R: Read> Read for PositionedRead<'a, R> {
44 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
45 let read = self.inner.read(buf)?;
46 self.position += read;
47 Ok(read)
48 }
49 }
50
51 #[cfg(test)]
52 mod test {
53 use super::*;
54 use io::{self, Cursor};
55 #[test]
56 fn test_disassemble_errors_at_end() {
57 let mut cursor = Cursor::new(&[0xff]);
58 let err = Inst::decode(&mut cursor).unwrap_err();
59 assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
60 assert_eq!(
61 err.get_ref().map(|x| x.to_string()),
62 Some("Extended instruction missing operand".into())
63 );
64 }
65 }